2010-09-17 93 views
3

我有一個問題,用不同的對象類型創建某種形式的層次結構。我有擁有另一個類的成員的類,像這樣:解決交叉引用

class A 
{ 
public: 
    A(){} 
    ~A(){} 

    void addB(B* dep){ 
     child = dep; 
     dep->addOwner(this); 
    } 
    void updateChild(){ 
     child->printOwner(); 
    } 
    void print(){ 
     printf("Printing..."); 
    } 
private: 
    B* child; 
}; 

這是B類:

class B 
{ 
public: 
    void addOwner(A* owner){ 
     ownerObject = owner; 
    } 

    //ISNT WORKING 
    void printOwner(){ 
     ownerObject->print(); 
    } 

private: 
    A* ownerObject; 
}; 

呼喚「B」淘汰類的函數「A」的工作方式好,但反過來試圖給出編譯器錯誤,因爲A沒有在B中定義。它實際上是通過使用include和forward聲明,但我想它是一個編譯器無法解決的交叉引用問題。

有沒有機會解決這個問題,還是應該重新考慮我的設計?

回答

8

你說你已經使用的A預先聲明,而不是包括解決您的循環依賴問題標題A被定義,所以你已經知道如何避免循環包含。但是,您應該知道what is possible and what is not with incomplete types(即已向前聲明的類型)。

對於您的情況,您嘗試在具有不完整類型的對象上調用成員函數print;編譯器對此類型一無所知,除了它將在某個時刻定義,所以它不允許你這樣做。解決的辦法是刪除從B頭的printOwner成員函數的實現,並把它變成一個實現文件:

//B.hpp 

class A; // forward declaration 

class B 
{ 
    public: 
    void addOwner(A* owner); 

    void printOwner() const; // I think this member function could be const 

    private: 
    A* ownerObject; 
}; 

//B.cpp 

#include "B.hpp" 
#include "A.hpp" // here we "import" the definition of A 

void B::addOwner(A * owner) 
{ 
    ownerObject = owner; 
} 

void B::printOwner() const 
{ 
    ownerObject->print(); //A is complete now, so we can use its member functions 
} 

你可能做同樣的事情在A頭。

2

你可能應該重新考慮你的設計,因爲一個親密的親子關係通常是一種代碼味道。

但是,你可以讓編譯器高興:

#include <cstdlib> 
#include <cstdio> 

class A 
{ 
public: 
    A(){} 
    ~A(){} 

    void addB(class B* dep); 
    void updateChild(); 
    void print(){ 
     printf("Printing..."); 
    } 
private: 
    class B* child; 
}; 

class B 
{ 
public: 
    void addOwner(A* owner){ 
     ownerObject = owner; 
    } 

    //ISNT WORKING 
    void printOwner(){ 
     ownerObject->print(); 
    } 

private: 
    A* ownerObject; 
}; 

void A::addB(class B* dep){ 
    child = dep; 
    dep->addOwner(this); 
} 

void A::updateChild(){ 
    child->printOwner(); 
} 



int main() 
{ 
    return 0; 
} 
+0

謝謝!這個「設計」背後的真正想法是擁有一個類(在這個例子中是A),它作爲許多抽象類(「B」)的容器,因此所有的「B」擴展了「A 「基於他們的具體實施。對於所有B對象的相同功能,我在A中創建了一個實現,因爲如果有10個B對象具有相同的功能,這沒有意義。至少這也是一個同步問題。 – SideEffect 2010-09-17 13:24:00

+0

@ user450556:聽起來像你可能想看看基於策略的設計 – 2010-09-17 18:38:49

0

你應該移到B :: printOwner實施.cpp文件。

2

您可以使用前置聲明,並定義的成員函數的類之外,即

// A.h 
class B; 
class A { public: 
    void addB(B* dep); // don't define addB here. 
    ... 
}; 

// B.h 
class A; 
class B { public: 
    void addOwner(A* owner); // don't define addOwner here. 
    ... 
}; 

// A.cpp 
#include "A.h" 
#include "B.h" 
void A::addB(B* dep) { 
    ... 
} 

// B.cpp 
// similar.