[C++]multiple definitions and undefined reference

Online-Skater

Erfahrenes Mitglied
Hallo Tutorianer

Leider kann man Template-Klassen nicht so kapseln wie normale Klassen in header und sourcefile. Daher muss man dies zusammen kompilieren lassen. Nun besteht aber das Problem, wenn man diese Header-Datei in mehreren Dateien inkludet und zwar wie im Titel beschrieben: multiple definitions of... Wie kann man das lösen ?

Diese Loggerklasse hat nur eine Funktion mit einem Template, vllt weis jemand wie man write() auch ohne template so gestalten kann, damit alle zumindest Standardtypen erfasst werden, ohne zu überladen.
C++:
#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED

#include <iostream>
#include <fstream>
#include <ctime>
#include "version.h"

#define LOG_NAME "JAE.log"

/****************************************************//**
 * Namespace des Projektes
 ********************************************************/
namespace jae
{
    /****************************************************//**
     * The logger writes (error)messages to a logfile.
     ********************************************************/
  class JAE_Logger
  {
    public:
    	JAE_Logger(bool aCreateNewFile = false);
        ~JAE_Logger();

        void error(const char*, const char*, const char* aType = "ERROR");
        void writeln();

        template<class T>
        void write(T,bool aNewLine = false);

    private:
        const char* getTime(void);
        std::ofstream _pLogFile;
  };

/****************************************************//**
 * Constructor of the class. Creates a new file.
 ********************************************************/
JAE_Logger::JAE_Logger(bool aCreateNewFile)
{
  if(aCreateNewFile)
  {
    _pLogFile.open(LOG_NAME, std::ios::out);
    if (_pLogFile)
    {
      _pLogFile << "*********************************************************************\n"
                << "**                  JUST ANOTHER ENGINE - Logfile                  **\n"
                << "*********************************************************************\n"
                << "Version: " << JAE_BUILD_VERSION << " " << JAE_BUILD_STATE << " ("
                << JAE_BUILD_DATE << "." << JAE_BUILD_MONTH << "." << JAE_BUILD_YEAR << ")\n\n";
    }
  }
}

/****************************************************//**
 * Destructor of the class.
 ********************************************************/
JAE_Logger::~JAE_Logger()
{
  _pLogFile.close();
}

/****************************************************//**
 * This method writes the systemtime to the logfile.
 ********************************************************/
const char* JAE_Logger::getTime(void)
{
  time_t Zeitstempel = time(0);
  tm *nun = localtime(&Zeitstempel);;
  return asctime(nun);
}

/****************************************************//**
 * This method adds a new line to the file.
 ********************************************************/
void JAE_Logger::writeln()
{
  if (_pLogFile)
  {
    _pLogFile << std::endl
              << "--------------------------------------- "
              << getTime()
              << std::endl;
  }
  std::cout << std::endl;
}

/****************************************************//**
 * This method writes any standard type in the logfile.
 * @param aValue write content
 * @param aNewLine write new line
 ********************************************************/
template<class T>
void JAE_Logger::write(T aValue, bool aNewLine)
{
  if (_pLogFile)
  {
    _pLogFile << aValue;
    if (aNewLine)
    {
      writeln();
    }
  }
  std::cout << aValue << std::endl;
}

/****************************************************//**
 * This method writes an errormessage to the logfile.
 * @param aFunctionName source of the error
 * @param aMessage text of the message
 * @param aType errortype
 ********************************************************/
void JAE_Logger::error(const char* aFunctionName, const char* aMessage, const char* aType)
{
  if (_pLogFile)
  {
    _pLogFile << std::endl
              << ">>> " << aType << " <<< [ " << aFunctionName << " ]"
              << std::endl << aMessage << std::endl;
    writeln();
  }
  std::cout << std::endl << ">>> " << aType << " <<< [ " << aFunctionName << " ]"
            << std::endl << aMessage << std::endl;
}

} //namespace jae

#endif // LOGGER_H_INCLUDED

Das Problem besteht aber weiterhin, da ich noch mehrere Template-Klassen habe, die mehrfach wo eingebunden werdne müssen.... Danke für eure Aufmerksamkeit.

mfg :)
 
Zuletzt bearbeitet:
Hallo,

was passiert denn, wenn du nur die Definition der Template-Methode in der Headerdatei belässt und die Definitionen der anderen in eine extra Quelldatei auslagerst?

Grüße,
Matthias
 
Dankeschön

Jetzt habe ich es kapiert ;)
Bei Templateartigen Funktionen/Klassen wird eine Ausnahme gemacht, normale Memberfunktionen müssen aber in das Sourcefile. Alles klar so funktioniert es. :)
 
Zurück