解决交叉引用问题

7

我有一个问题,需要用不同的对象类型来创建某种层次结构。我有一个类,其中包含另一个类的成员,就像这样:

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"的函数是完全可行的,但反过来尝试会导致编译错误,因为B中未定义A。实际上,可以使用include和前向声明来解决这个问题,但我猜测这是一个交叉引用问题,编译器无法解决。

有没有可能解决这个问题,或者我应该重新考虑我的设计?

4个回答

12
你说你已经通过使用 A 的前向声明而不是包含定义 A 的头文件来解决了循环依赖问题,因此你已经知道如何避免循环包含。然而,你应该意识到 不完整类型的可能性和不可能性(即已进行前向声明但未定义的类型)。
在你的情况下,你试图调用具有不完整类型的对象的成员函数 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 标签的头部做同样的事情。


3

您可以使用前向声明,并将成员函数的定义放在类的外部,如下:

// 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.

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

谢谢!这个“设计”的真正想法是有一个类(在这个例子中是A),它作为许多抽象类(“B”)的容器,以便所有“B”基于它们的具体实现扩展“A”的功能。对于所有B对象都相同的功能,我在A中创建了一个实现,因为让10个B对象具有相同的功能是没有意义的。至少这也会是一个同步问题。 - SideEffect
@user450556:听起来你可能想要研究一下基于策略的设计。 - John Dibling

0
你应该将B::printOwner的实现移动到.cpp文件中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接