如何在源文件中定义 class 并在头文件中声明它(无需使用 `class::method` 语法定义 class 方法)?

How to define a class in a source file and declare it in a header file (without having to define the class methods using `class::method` syntax)?

我正在查看一个 library on github,其中一个头文件中包含以下内容:

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(); }
};

以及源文件中的以下内容:

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 ) );
}

为什么当我将源文件中的上述内容替换为以下内容时,编译器会报错"redefinition"?我以为头文件只包含声明,而源文件实际上定义了 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 ) );
} 
}

如何使用上述样式而不是 Util::log 来定义 class?

当你有像

这样的代码块时
class Util
{
    ...
}

您正在定义 class。您提供的第一个示例是定义 class 和声明 header 文件中的函数。源文件定义函数。

当您尝试将 class Util 行放在带有大括号的源文件中时,编译器认为您正在定义一个新的 class。这就是您收到错误的原因。

如果您只是将 class Util; 放在一行中,那么您将 声明 class。 class 声明告诉您 class 存在,但不会告诉您有关 class.

的任何信息

如果去掉header文件,在源文件中加入如下内容,可以编译,但其他源文件将无法使用class(因为它们不再让 header 文件为他们定义它。

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 ) );
    } 
}

如果你想让一个class被多个源文件使用,那么你需要在一个header中定义class。然后,您也可以在 header 中定义函数(出于很多原因通常不鼓励这样做),或者您可以使用 Util::log 语法在源文件中定义函数(推荐做法)。

Header 文件(以及它们的使用方式)是对 C 和 C++ 的常见抱怨。这就是为什么较新的语言(如 Java 和 C#)倾向于不使用 header 文件的原因。但是,您引用的库定义此 class 的方式应根据 C++ 最佳实践定义 classes。

您真正的问题是您误解了 class 的定义。您描述的 class 定义不是 class 定义。

github中header中class的声明实际上是class[=]的定义 10=]。在该定义中,还定义了成员函数 toString()(实际上是 Util::toString())。

源文件然后定义了 class 的两个成员函数(大概是在包含 header 之后,尽管您没有显示)。这两个函数定义不是 class.

的定义

通常的做法其实是github图书馆已经做到的,而你正在努力改变。

  • 在 header 文件中定义 classes。这样,每个需要使用 class 的编译单元都包含 header,并看到 class 定义。这是 non-trivially 使用 class 所必需的(例如实例化实例、访问成员等)。
  • 在编译单元中定义成员函数(它们只会被定义一次)或在 header 中定义为内联函数(多个编译单元可以看到函数定义。实现(即编译器)采用在使用此类函数时注意事项以防止出现多重定义问题。

当您更改它时,您已经在源文件中引入了 class Util 的定义。如果在包含 header 之后发生这种情况,编译器将看到 class Util 的两个定义。这就是您的编译器抱怨定义的原因。