解决交叉引用问题

时间:2010-09-17 12:34:20

标签: c++

我在创建具有不同对象类型的某种形式的层次结构时遇到问题。我有一个类,其中包含另一个类的成员,如下所示:

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;
};

在类“A”之外调用“B”的函数工作正常但反之亦然会产生编译器错误,因为A未在B中定义。它实际上是通过使用包含和前向声明,但我猜测它是编译器无法解决的交叉引用问题。

有没有机会解决这个问题,还是应该重新考虑我的设计?

4 个答案:

答案 0 :(得分:10)

你说你已经通过使用A的前向声明解决了你的循环依赖问题,而不是包含定义A的标题,所以你已经知道如何避免循环包含。但是,您应该知道what is possible and what is not with incomplete types(即已经声明的类型)。

在您的情况下,您尝试在具有不完整类型的对象上调用成员函数print;编译器对此类型一无所知,除了它将在某个时刻定义,因此它不允许您这样做。解决方案是从printOwner标头中删除B成员函数的实现,并将其放入实现文件中:

//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标题中执行相同的操作。

答案 1 :(得分: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;
}

答案 2 :(得分: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.

答案 3 :(得分:0)

您应该将B :: printOwner实现移动到.cpp文件。