c++ - 如何在源文件中定义一个类并在头文件中声明它(不必使用 `class::method` 语法定义类方法)?

标签 c++ class header-files declaration one-definition-rule

我正在看 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 ) );
}

为什么当我将源文件中的上述内容替换为以下内容时,编译器会提示“重新定义”?我以为头文件只包含声明,而源文件实际上定义了类?

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
{
    ...
}

您正在定义类。您提供的第一个示例是定义类并声明头文件中的函数。源文件定义函数。

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

如果您只是将 class 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 ) );
    } 
}

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

头文件(以及它们的使用方式)是对 C 和 C++ 的常见提示。这就是为什么较新的语言(如 Java 和 C#)倾向于不使用头文件的原因。但是,您引用的库正在按照 C++ 最佳实践定义类的方式定义此类。

关于c++ - 如何在源文件中定义一个类并在头文件中声明它(不必使用 `class::method` 语法定义类方法)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46375619/

相关文章:

python - pep 232 也适用于实例方法吗?

c++ - 如何在 C++ 源代码中读取 CMake 变量

c++ - 将所有代码放在 C++ 头文件中的优点和缺点?

c++ - 定义一个符号,它可能是 boost spirit 中文字函数的一部分

c++ - 可以用参数包编译c++17 lambda继承的编译器

c++ - 将 dynamic_cast 与引用和指针一起使用时的行为差异

ruby - 这段 Ruby 代码的作用是什么? : def self. 元类;类<< self ;自己;结尾;结尾

c++ - 临时结构对象构造函数奇数调用

c# - 类继承 : recreate base class items (or instance) from a property of the inherited class

c - 结构定义(不是实例化)应该放在头文件中吗?