2017-06-22 26 views
0

为什么不编译?声明,然后定义一个类方法 - 为什么会出错?

class Test 
{ 
    void foo(); 
    void foo() 
    { } 
}; 

但这些将编译:

void bar(); 
void bar() 
{ } 

// In same header/file 
class Test 
{ 
    void foo(); 
}; 
void Test::foo() 
{ } 

编译器会说,给定的方法cannot be overloaded。方法Test::foo未被重载 - 它是具有完全相同签名的相同函数。

+0

@StoryTeller ^应该是一个答案:) – Curious

+1

每个成员必须在类内声明一次。每个定义也是一个声明。 –

+0

@StoryTeller很好的答案不需要标准报价!特别是对于这样的事情。标准报价的答案是如果正确的答案虽然 – Curious

回答

5

它被C++标准明确禁止。那里在[class.mfct/1]

的成员函数可以在它的类定义中所定义,其中 情况下,它是一个内联成员函数,或者它可以 其类定义之外,如果它已经被声明中定义,但在其类定义中没有定义 。在类定义之外出现 的成员函数定义应出现在包含类定义的名称空间作用域 中。 除成员函数定义 显示类定义的外侧,并且除了的类模板和构件 函数模板的成员函数明确 特([temp.spec])出现的类 定义之外,一个成员函数不得重新声明。

+0

没有说明为什么全局函数声明/定义允许完全相同的方式,但不是在一个类中。 – Ajay

+0

@Ajay - 当然,它被陈述为允许,在另一节**免费函数**声明。这是关于**成员**,并且在报价中是明确的。 – StoryTeller

0
void foo(); 

void foo() {} 

是在一个类定义声明函数的方法有两种。第一个只声明函数,第二个声明函数并实现它。因此,编译器假定您将重新声明相同的函数并且不是正确的重载,因为函数签名在两者中都是相同的。

+0

不回答问题。 – Ajay

1

这只是它在C++中的方式。不允许重新申报班级成员(除非您将定义为作为另一个申报)。只要您遵守ODR,就可以重新声明名称空间成员。

+0

必须有一个有效的理由。 'T x()'不调用构造函数,而是调用函数,因为C++编译器必须首先考虑C语言规则。同样,ODR规则对于免费级和职业级职能也不会有所不同。 – Ajay

1

为什么不编译?

class Test { 
    void foo(); 
    void foo() { }; // wrong 
}; 

因为,StoryTeller和其他人回答说,你声明和定义两次相同成员函数void Test::foo(void)(和foo内部类的定义是隐含inline)。

如果你想在你的头文件后级定义一个成员函数,你会更好的明确声明它为inline这样的:

class Test { 
    inline void foo(); 
}; 

定义成员函数(例如以下以相同的标头文件):

void Test::foo() { 
    // body of Test::foo 
} 

顺便说一句,如果声明一个成员函数中包含上述以外的定义,并且该成员函数不是inline但是在一些头文件定义其被包含在多个翻译单元,该函数将被多重定义,并且链接器会投诉。

+1

在这种情况下,很容易忘记内联说明符对于正确链接的重要性。 +1 – StoryTeller

+0

内联与声明/定义有什么关系?我们可以对全局函数做同样的事情,但不能用类方法。为什么?另外,即使'inline'属性应用于自由函数,它仍然会编译。 – Ajay

+0

您可能在链接时遇到问题。 –

相关问题