2017-09-23 236 views
1

我在看一個library on github其在頭文件下列操作之一:如何在源文件中定義一個類並在頭文件中聲明它(而不必使用`class :: method`語法來定義類方法)?

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

回答

1

當你有一個像

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

如果你想讓一個類被多個源文件使用,那麼你需要在一個頭文件中定義這個類。然後你可以在頭文件中定義函數(通常由於很多原因而不鼓勵),或者你可以使用Util::log語法來定義源文件中的函數(推薦的做法)。

頭文件(以及它們需要使用的方式)是關於C和C++的常見抱怨。這就是爲什麼新語言(如Java和C#)傾向於不使用頭文件。但是,您引用的庫是按照C++最佳實踐來定義類的方式。

2

你真正的問題是你誤解了什麼是類定義。你所描述的類定義不是類定義。

來自github的頭文件中類的聲明實際上是Util類的定義。在該定義中,還定義了成員函數toString()(實際上爲Util::toString())。

然後,源文件定義了該類的兩個成員函數(大概在包含頭部之後,雖然沒有顯示)。這兩個函數定義不是類的定義。

通常的做法實際上是github庫所做的,而您正在嘗試更改。

  • 定義頭文件中的類。這樣,每個需要使用該類的編譯單元都會包含頭文件,並可以看到類定義。非平凡地使用這個類是非常必要的(例如實例化實例,訪問成員等)。
  • 在編譯單元中定義成員函數(在這些函數中只能定義一次)或者在頭文件中作爲內聯函數(其中多個編譯單元可能會看到函數定義),實現(即編譯器)負責處理事情以防止出現問題這樣的功能工作的多個定義的時候。

當你改變了它,你就介紹Util類的定義到源文件。如果包括頭部後發生時,編譯器會看到兩個定義Util。這就是爲什麼你的編譯器抱怨定義。

相關問題