2010-09-17 118 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.