C++ 如何在源文件中定义类并在头文件中声明它(而不必使用`class::method`语法定义类方法)?
我正在查看一个在其中一个头文件中包含以下内容的文件:C++ 如何在源文件中定义类并在头文件中声明它(而不必使用`class::method`语法定义类方法)?,c++,class,header-files,declaration,one-definition-rule,C++,Class,Header Files,Declaration,One Definition Rule,我正在查看一个在其中一个头文件中包含以下内容的文件: 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; re
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(); }
};
为什么当我用下面的替换源文件中的上述内容时,编译器会抱怨重新定义?我认为头文件只包含声明,而源文件实际上定义了类
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 ) );
}
}
如何使用上述样式而不是Util::log来定义类?当您有一块类似
class Util
{
...
}
您正在定义类。您给出的第一个示例是定义类并在头文件中声明函数。源文件正在定义函数
当您试图将类Util行和大括号放在源文件中时,编译器认为您正在定义一个新类。这就是为什么你会出错
如果你只是把类Util;在一行中,您将声明该类。类声明告诉您该类存在,但不告诉您有关该类的任何信息
如果删除了头文件并将以下内容放在源文件中,它将被编译,但其他源文件将无法使用该类,因为它们将不再具有为它们定义该类的头文件
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 ) );
}
}
如果希望一个类由多个源文件使用,则需要在头文件中定义该类。然后,您可以在头文件中定义函数,因为很多原因通常不鼓励这样做,或者您可以使用Util::log语法在源文件中定义函数,这是推荐的做法
头文件及其使用方式是C和C++的常见抱怨。这就是为什么像Java和C这样的较新语言倾向于不使用头文件的原因。但是,您引用的库定义了类,应该根据C++最佳实践定义类。
当您有一个代码块时,比如class Util
{
...
}
您正在定义类。您给出的第一个示例是定义类并在头文件中声明函数。源文件正在定义函数
当您试图将类Util行和大括号放在源文件中时,编译器认为您正在定义一个新类。这就是为什么你会出错
如果你只是把类Util;在一行中,您将声明该类。类声明告诉您该类存在,但不告诉您有关该类的任何信息
如果删除了头文件并将以下内容放在源文件中,它将被编译,但其他源文件将无法使用该类,因为它们将不再具有为它们定义该类的头文件
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 ) );
}
}
如果希望一个类由多个源文件使用,则需要在头文件中定义该类。然后,您可以在头文件中定义函数,因为很多原因通常不鼓励这样做,或者您可以使用Util::log语法在源文件中定义函数,这是推荐的做法
头文件及其使用方式是C和C++的常见抱怨。这就是为什么像Java和C这样的较新语言倾向于不使用头文件的原因。但是,您引用的库定义了类,应该根据C++最佳实践来定义类。
您真正的问题是误解了类定义。您所描述的类定义不是类定义 github头中的类声明实际上是类Util的定义。在该定义中,成员函数toString实际上还定义了Util::toString 然后,源文件定义了该类的两个成员函数,可能是在包含了头之后,尽管您还没有显示这一点。这两个函数定义不是类的定义 通常的做法实际上是github库所做的,您正在尝试改变 在头文件中定义类。这样,需要使用该类的每个编译单元都包括头,并可以看到类定义。这对于非平凡地使用类是必要的,例如实例化实例、访问成员等。 在编译单元中定义成员函数,在编译单元中成员函数只能定义一次,或者在头中定义为内联函数,在内联函数中,多个编译单元可以看到函数定义。在使用这些函数时,编译器负责防止出现多定义问题。当您更改它时,您已经在源文件中引入了类Util的定义。如果在包含头之后发生这种情况,编译器将看到类Util的两个定义。这就是编译器抱怨定义的原因。您真正的问题在于您误解了类定义是什么。您所描述的类定义不是 类定义 github头中的类声明实际上是类Util的定义。在该定义中,成员函数toString实际上还定义了Util::toString 然后,源文件定义了该类的两个成员函数,可能是在包含了头之后,尽管您还没有显示这一点。这两个函数定义不是类的定义 通常的做法实际上是github库所做的,您正在尝试改变 在头文件中定义类。这样,需要使用该类的每个编译单元都包括头,并可以看到类定义。这对于非平凡地使用类是必要的,例如实例化实例、访问成员等。 在编译单元中定义成员函数,在编译单元中成员函数只能定义一次,或者在头中定义为内联函数,在内联函数中,多个编译单元可以看到函数定义。在使用这些函数时,编译器负责防止出现多定义问题。 当您更改它时,您已经在源文件中引入了类Util的定义。如果在包含头之后发生这种情况,编译器将看到类Util的两个定义。这就是编译器抱怨定义的原因