2011-09-07 132 views
5

鑑於以下類是兩個獨立的頭文件,並可以以任意順序出現:C++類的原型衝突

//TestB.h 
class TestB; //Forward declaration for a later operator= in a centralised header 

class TestA 
{ 
    const TestA&operator=(const TestB); //defined in Test.h 
}; 

和:

//TestA.h 
class TestA; //Forward declaration for a later operator= in a centralised heaer 

class TestB 
{ 
    const TestB&operator=(const TestA); //defined in Test.h 
}; 

如何避免原型衝突?

幫助表示讚賞。

我絕對向大家道歉!我原本打算在那裏引用(operator = arguments中的&符號 - 我絕對不會通過複製bar簡單POD來傳遞),而僅僅是關於原型衝突的問題!我想這表明證明閱讀的重要性!我已經接受了原來的(我錯誤的)背景下的答案。

我只是轉過身去了幾分鐘,並沒有意識到錯誤!

+1

你是什麼意思「原型衝突」? –

+2

這裏沒有錯 - 這將工作正常。您需要更好地解釋錯誤,並使用真實的代碼。 –

+1

@Als:你可以通過值聲明不完整類型的函數;直到類型定義之後才能定義或調用它們。 –

回答

4

您將對類的引用作爲參數傳遞。這樣,一個類和它的成員函數可以在不知道另一個的情況下被聲明。

//TestB.h 
class TestB; //Forward declaration for a later operator= in a centralised header 

class TestA 
{ 
    const TestA&operator=(const TestB &); //defined in TestB.h 
}; 

和:

//TestA.h 
class TestA; //Forward declaration for a later operator= in a centralised heaer 

class TestB 
{ 
    const TestB&operator=(const TestA *); //defined in TestA.h 
}; 

在這之後,你必須包括TestA.h和TestB.h兩個TestA.cpp和TestB.cpp文件能夠定義這些成員功能。

+0

沒有必要改變語義,只要你不嘗試*定義*或者你可以**聲明函數來獲取或返回一個*不完整類型* *調用*這些函數。 –

4

我原來的答案似乎是完全錯誤的。

檢查您是否在所有頭文件中都包含了警衛,這樣您就不會收到無限的包含鏈。然後,包括在每一個執行標題:

// A.cpp 
#include "A.h" 
#include "B.h" // for complete type TestB 

const TestA & TestA::operator=(const TestB) { /* ... */ } 

// B.cpp 
#include "B.h" 
#include "A.h" // for complete type TestA 

const TestB & TestB::operator=(const TestA) { /* ... */ } 

請注意,這樣的結構能產生好奇的設計情況要麼TestATestB的任何消費者誰希望呼叫話務員必須始終包含既有A.hB.h,這是非常細微的,但也有點意外。爲包含兩個頭文件的客戶端添加一箇中間頭文件可能是值得的,或者爲頭文件本身添加相互包含(帶有警衛!)。


你不能在你寫的方式解決這個問題,因爲你有一臺出無限遞歸的依賴。

你平時做到這一點是通過參考,而不是複製來傳遞參數,因爲通過引用傳遞的方式確實需要完整的類型的知識:

const TestA & operator=(const TestB &); 
            ^^^^^ 
            vvvvv 
const TestB & operator=(const TestA &); 

+2

即使參數類型不完整,您也可以聲明以值爲參數的函數。直到類定義之後,才能定義該函數。 –

+0

@Mike:我很驚訝,我真的認爲這是不允許的! –

+0

@Kerrek SB:只要函數在頭文件中沒有* defined *或* called *,甚至不需要添加循環包含,並且* call *或* define這些成員的翻譯單元函數包含兩個頭文件。 –

0

前向聲明僅適用於聲明類型的指針和引用......它們不能用於實際的複製操作,也不能用於將類實例聲明爲非靜態類數據成員。如果你試圖這樣做,編譯器會給你一個不完整類型的錯誤,因爲沒有足夠的信息給編譯器提供有關實際類型組成的信息(例如它有多大等等)。 ),以便它可以構造主類或確定分配給類方法參數的多少堆棧空間。

1

那兒有頭沒有實際的問題,只要他們只聲明成員函數,不提供定義。也就是說,如果成員函數的定義在包含頭文件的.cpp文件中,並且在頭文件中沒有對任何函數的調用,它應該可以很好地工作。

有一種普遍的誤解,認爲你不能使用任何看起來像與前聲明的類型,但事實是,你不能創建該類型的對象或創建該類型的成員變量,但是你可以通過值聲明或返回這些類型的函數

你不能,在另一方面,定義呼叫這些功能,因爲這將需要不完全類型的對象的創建。