I am looking at a library on github which has the following in one of the header files:
class Util
{
public:
static void log( const string& message );
static void log( const char* message );
template<typename T>
static inline string toString(T t) { stringstream s; s << t; return s.str(); }
};
and the following in the source file:
void Util::log( const string& message )
{
const string& logMessage = "[cppWebSockets] " + message;
syslog( LOG_WARNING, "%s", logMessage.c_str( ) );
}
void Util::log( const char* message )
{
log( string( message ) );
}
Why is it that when I replace the above contents in the source file with the below the compiler complains of "redefinition"? I thought the header file only held the declaration whereas the source file actually defines the class?
class Util
{
public:
void Util::log( const string& message )
{
const string& logMessage = "[cppWebSockets] " + message;
syslog( LOG_WARNING, "%s", logMessage.c_str( ) );
}
void Util::log( const char* message )
{
log( string( message ) );
}
}
How to define the class using the above style instead of Util::log
?
When you have a block of code like
you are defining the class. The first sample you gave is defining the class and declaring the functions in the header file. The source file is defining the functions.
When you tried to put the
class Util
line in the source file with the braces, the compiler thinks you are defining a new class. That's why you get the error.If you just put
class Util;
on a line, then you would be declaring the class. A class declaration tells you that the class exists, but does not tell you anything about the class.If you removed the header file and put the following in the source file, it would compile, but other source files would not be able to use the class (because they would no longer have the header file defining it for them).
If you want to have a class be used by multiple source files, then you will need to define the class in a header. You could then define the functions inside the header as well (usually discouraged for a lot of reasons), or you could use the
Util::log
syntax to define the function in a source file (the recommended practice).Header files (and the way they need to be used) are a common complaint about C and C++. That is why newer languages (like Java and C#) tend not to use header files. However, the library you referenced is defining this class the way classes should be defined according to C++ best practices.
Your real problem is that you are misunderstanding what a class definition is. What you are describing as a class definition is not a class definition.
The declaration of the class in the header from github is actually a definition of the class
Util
. Within that definition, the member functiontoString()
(actuallyUtil::toString()
) is also defined.The source file then defines two member functions of that class (presumably after including the header, although you have not shown that). Those two function definitions are not definitions of the class.
The usual practice is actually what the github library has done, and you're trying to change.
When you've changed it, you've introduced a definition of class
Util
into the source file. If that occurs after including the header, the compiler will see two definitions of classUtil
. That is why your compiler is complaining about definition.