问题
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
?
回答1:
When you have a block of code like
class Util
{
...
}
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).
class Util
{
public:
void log( const string& message )
{
const string& logMessage = "[cppWebSockets] " + message;
syslog( LOG_WARNING, "%s", logMessage.c_str( ) );
}
void log( const char* message )
{
log( string( message ) );
}
}
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.
回答2:
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 function toString()
(actually Util::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.
- Define classes in header files. That way, every compilation unit that needs to use the class includes the header, and sees the class definition. Which is necessary to non-trivially use the class (e.g. to instantiate instances, access members, etc).
- Define member functions in the compilation unit (where they will only be defined once) OR in the header as inline functions (where multiple compilation units may see the function definition. The implementation (i.e. compiler) takes care of things to prevent problems of multiple definition when working with such functions.
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 class Util
. That is why your compiler is complaining about definition.
来源:https://stackoverflow.com/questions/46375619/how-to-define-a-class-in-a-source-file-and-declare-it-in-a-header-file-without