2017-06-22 139 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

您可能在鏈接時遇到問題。 –

相關問題