2015-02-10 62 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