2016-03-19 37 views
1

這是簡化代碼只是爲了顯示我的問題:
的main.cpp無效使用不完全類型的錯誤

#include "one.hpp" 
#include <iostream> 


int main(){ 
One one; 
std::cout << one.two->val; 
} 

one.hpp:

struct Two; <- forward declare Two 
struct One{ 
One(); 
~One() { delete two;} 
Two* two; 
}; 

one.cpp

#include "one.hpp" 
struct Two{ 
int val; 
}; 

One::One(): two(new Two()) {} 

編譯時,我得到錯誤使用不完整的類型'struct Two'。 我認爲,因爲兩個是不完整的類型,我只是不能參考其領域... 我想知道是否有任何方法來隱藏兩個實現在一個cpp文件,並使用它在另一個cpp文件使用這種前瞻性聲明?問題來自於創建API,我想隱藏某些類的實現。

+1

確定你可以,但是你正在通過試圖查看它來侵犯'main'中隱藏的'Two''(沒有'Two'成員或方法的訪問權限,而沒有包含'Two ')。 – crashmstr

+0

謝謝大家的回答,關於析構函數的評論也很有幫助。所以我現在的理解是,使用這種前向聲明來隱藏實現和類定義,就像在pimpl習語中一樣,如果我們在一個定義發生的翻譯單元中提到了forward聲明的類,那麼它就是有意義的,否則我將不得不引入class在每個地方定義它的方法/字段(因此不會進行類定義隱藏)。所以我認爲我的設計決定是不正確的...... – user3655463

+0

_「我認爲我的設計決定是不正確的」_我不確定我是否理解你是如何得出這個結論的。你也可以在頭文件中隱藏實現。看我下面的例子。 – ZDF

回答

3

您不能刪除不完整類型的對象。

解決方案是在one.cpp中定義析構函數。

one.hpp:

struct One { 
    ~One(); 
    // ... 
}; 

one.cpp:

// ... 

One::~One() { delete two; } 
+0

千萬不要錯過'std :: cout << one.two-> val;'in'main'。那也行不通。 – crashmstr

1

百科:「不透明指針是從普通隱藏接口的實現細節的方式客戶端,因此可以改變實現而不需要重新編譯使用它的模塊。「

struct opaque; 
struct interface 
{ 
    ~interface(); 
    void test(); 
    opaque* _p; 
}; 

頭文件沒有發佈到客戶端:

struct opaque 
{ 
    void test(); 
    //... 
}; 

interface實現文件:

#include "interface.h" 
#include "opaque.h" 

interface::~interface() 
{ 
    delete _p; 
} 

void interface::test() 
{ 
    _p->test(); 
} 
// ... 

opaque實現文件:

發佈給客戶

頭文件

#include "opaque.h" 

void opaque::test() 
{ 
// actual implementation 
} 
+0

好的,我看到了,但是我仍然必須在每個引用轉發結構的翻譯單元中包含'結構定義'(不知道如果濫用時不會導致代碼膨脹問題),無論如何,好的方面只是創建專用頭文件。 – user3655463

+0

由於客戶端不依賴它,因此包含實現標頭是正常的。關鍵是如果庫的實現發生變化,則生成時間很短。 – ZDF

相關問題