2015-02-10 96 views
1

我有這樣的.h文件一個C++ CLASSE:C++錯誤:多類函數的定義

#ifndef __GLWidget_h__ 
#define __GLWidget_h__ 

class PivotShape 
{ 
    // This is allowed 
    void do_something() { std::cout << "Doing something\n"; } 

    // This is not allowed 
    void do_something_else(); 
} 

// This is not allowed 
void PivotShape::do_something_else() 
{ 
    std::cout << "Doing something else\n"; 
} 

#endif 

如果我添加類聲明的一切似乎罰款內的方法。但是如果我在類聲明之外添加方法,我會得到類似這樣的錯誤:

/usr/share/qt4/bin/moc GLWidget.h > GLWidget_moc.cpp 
/programs/gcc-4.6.3/installation/bin/g++ -W -Wall -g -c -I./ -I/usr/include/qt4 GLWidget_moc.cpp 
/programs/gcc-4.6.3/installation/bin/g++ main.o GLState.o GLWidget.o MainWindow_moc.o GLWidget_moc.o -L/usr/lib/x86_64-linux-gnu -lQtGui -lQtOpenGL -lQtCore -lGLU -lGL -lm -ldl -o main 
GLWidget.o: In function `std::iterator_traits<float const*>::iterator_category std::__iterator_category<float const*>(float const* const&)': 
/home/<user>/<dir>/<dir>/<dir>/<dir>/<dir>/GLWidget.h:141: multiple definition of `PivotShape::do_someting_else()' 
main.o:/home/<user>/<dir>/<dir>/<dir>/<dir>/<dir>/GLWidget.h:141: first defined here 

我認爲重做是由Make文件中的這個片段引起的。我認爲.h文件被轉換爲_moc.cpp文件,這是允許多個夾雜物:

# Define linker 
LINKER  = /programs/gcc-4.6.3/installation/bin/g++ 

MOCSRCS  = $(QTHEADERS:.h=_moc.cpp) 

# Define all object files to be the same as CPPSRCS but with all the .cpp 
# suffixes replaced with .o 
OBJ   = $(CPPSRCS:.cpp=.o) $(MOCSRCS:.cpp=.o) 

這是什麼問題?如果是這樣,我該如何解決?如果不是,發生了什麼事?

我認爲在C++中將類方法包含在類聲明的主體中是非法的。如果這是合法的,那麼它似乎是解決問題的簡單方法。這合法嗎?

編輯:

我忘了提,我已經發現,聲明該方法爲inline的作品,但我想知道如何避免重複。

+3

**'inline' **可能現在就派上用場了。 – WhozCraig 2015-02-10 11:41:17

回答

8

你打破了一個定義規則;在標題中定義函數意味着每個包含標題的翻譯單元都有一個定義,並且通常只允許在程序中使用單個定義。

選項:

  • 移動功能定義爲一個源文件,所以只是一個定義;或
  • inline添加到函數定義中,放寬規則並允許多個定義;或
  • 在類中定義函數,這會使其隱式內聯。 (要回答你的最後一個問題,是的,這是合法的。)

另外,不要使用reserved names__GLWidget_h__

+0

謝謝。那麼發生什麼事是A.cpp和B.cpp都包含.h文件,導致多重定義?由於'#ifndef ...#endif'語句,沒有一個單獨的.cpp文件可能有多個包含。但是這不意味着.h文件中的所有類定義都會重複嗎?它們是隱式的「內聯」嗎?這就是爲什麼類中的函數隱式地「內聯」? – Schemer 2015-02-10 12:05:48

+1

@Schemer:是的,您會在每個翻譯單元(翻譯單元對應一個源文件及其包含的所有內容)中得到一個定義。包括警衛防止每個單位內有多個定義,但不要停止其他單位的定義。只要定義相同,就可以在多個單元中定義類定義,內聯函數,模板和各種其他事物。非內聯函數和變量只能定義一次。 – 2015-02-10 13:26:26

+1

要擴充Mike的說法:規則是「每個程序都應該包含每個非內聯函數或該程序中odr使用的變量的一個定義;不需要診斷」「不需要診斷」意味着任何否則就是未定義的行爲,即使在實踐中,我知道的所有編譯器都會爲多個定義(以及缺少的定義)指示錯誤。 – 2015-02-10 14:20:45

2

定義源文件中的函數或使用inline在類定義之外的頭文件中定義它。

請注意,您仍然可以在類定義中定義它,而不使用inline關鍵字。

相關:Member function definition