2017-09-01 51 views
0

所有解決方案,以圓形包括我看過只是「這種特殊情況下」,因爲「你」僅使用指針該類完整的類定義是沒有必要說的依賴性。循環包括依賴性/前置聲明

我遇到了這個問題,並使用前置聲明固定它。

我想知道什麼是你應該在你需要的其他類的兩個類的具體定義做。

而且,爲什麼使用指針類允許您使用正代替聲明一個類定義的?

回答

2

在什麼情況下您需要事先知道兩個類的規格?

一個不可能的情況是以下內容:

class A 
{ 
    B m_b; 
}; 

class B 
{ 
    A m_a; 
}; 

但是,由於類A的大小依賴於類B的大小,這是不可能的,但類B的大小取決於類A的大小當您嘗試構建其中一個時,您還將獲得無限系列A myA; myA.m_b.m_a.m_b.m_a....

如果你使用指針,你不需要知道的任何大小;指針總是相同的大小取決於你所在的平臺。系列消失了,因爲需要明確創建堆中的對象。

+0

我想到的一個例子是對象「A a」創建對象「B b」,但是在構造或道路某個點傳遞它自身的副本。但是「對象b」有一個類型爲A的成員變量。 我很確定你會這樣做的任何情況都會被認爲是糟糕的編程,但那是困擾我的問題。 感謝您的全面回答! – Spectral

+0

「傳遞給它一個副本」 - 你可以聲明一個函數,將一個不完整的類作爲參數或返回類型傳遞;直到看到類定義完成後才能定義或調用它。所以'A級; B類{public:void process(A); };'很好。 (即使在那裏,你可以使用'const A&'。) – aschepler

0

我想知道什麼是你應該當你需要在這兩個類別的具體 定義其他類做。

它可以用現代編譯器中的前向聲明和延遲定義完成。許多較早的編譯器只允許指向&引用前向聲明的類型。

下面是一個人爲的例子:

A.hpp

class B; 

class A 
{ 
public: 
    int32_t Value; 

    A(int32_t value) : Value(value) { } 

    int32_t Add(B b) const; 
} 

B.hpp

#include "A.hpp" 

class B 
{ 
public: 
    int32_t Value; 

    B(int32_t value) : Value(value) { } 

    int32_t Sub(A a) const; 
} 

AB.hpp

#include "A.hpp" 
#include "B.hpp" 

inline int32_t A::Add(B b) const 
{ 
    return this->Value + b.Value; 
} 

inline int32_t B::Sub(A a) const 
{ 
    return this->Value - a.Value; 
} 

此外,爲什麼使用指向類的指針允許您使用正向 聲明而不是類定義?

正向聲明只是名稱的編譯器。這個概念存在,所以你可以使用尚未定義的類型。這是必要的,因爲C++分析代碼的方式,它是C語言的一個非常重要的部分。 C++解析器實際上僅僅是隻向前文本處理器,在您使用宏時注入文本。這是一個概念上簡單的模型,它使得C/C++編譯器在早期更容易編寫。將它與C#/ Java進行對比,您只需使用/ import,然後用簡單的語法快速創建類之間的循環依賴關係。

指針實際上只是整數,與shortint類似,但是具有語言強制的特殊語義和基於CPU架構的編譯時已知的固定大小。這使編譯器處理指針聲明非常簡單。

前向聲明有利於循環依賴和實現隱藏(這也正好加快了編譯時間)。考慮pimpl idiom。沒有前向聲明,沒有類型安全的方法來隱藏實現細節。