问题引出

C++中两个类互相包含是无法通过编译的:

class B;
class A{
    B b;
}
class B{
    A a;
}

编译报错:

main.cpp:7:4: error: field ‘b’ has incomplete type ‘B’
  B b;
    ^
main.cpp:5:7: note: forward declaration of ‘class B’
 class B;
       ^

原因很简单,创建A时要先创建B,然后创建B又要创建A,反反复复就会进入死循环,编译肯定报错。

解决方案一:使用指针

当两个类要互相包含时,要求其中一个类必须使用指针的形式,并且包含类中对于被包含类的调用不能早于被包含类的定义之前。

第一句话好理解,把代码改成以下形式即可:

class B; // B的声明不能省略
class A{
    B *b;
};
class B{
    A a;
};

对于第二句话包含类中对于被包含类的调用不能早于被包含类的定义之前的理解:

class B;
class A{
    void showB();/*{ // B.value的声明位于该语句之后,不能调用
            cout << b->value << endl;
        }*/
    B *b;
};

// 调用失败,因为b->value此时并没有声明
void A::showB(){
    cout << b->value << endl;
}

class B{
public:
    B(){
        value=1;
    }
    A a;
    int value;
};

编译出错:

main.cpp:14:11: error: invalid use of incomplete type ‘class B’
  cout << b->value << endl;
           ^~
main.cpp:5:7: note: forward declaration of ‘class B’
 class B;
       ^
main.cpp:14:13: error: invalid use of incomplete type ‘class B’
  cout << b->value << endl;
             ^~~~~
main.cpp:5:7: note: forward declaration of ‘class B’
 class B;

需要把A::showB()的定义移到类B的声明之后:

class B{
public:
    B(){
        value=1;
    }
    A a;
    int value;
};

void A::showB(){
    cout << b->value << endl;
}

解决方案二:不实例对象B

如果在对象A中仅仅只是使用对象B作为成员函数的形参,则可以不用使用指针。

class B;
class A{
    void showB(B b);
};


class B{
public:
    B(){
        value=1;
    }
    A a;
    int value;
};

void A::showB(B b){
    cout << b.value << endl;
}

同样,也和上面一样,A中使用B也要在B的声明之后,把A::showB() 放到class B 之前编译也会不通过。

最后修改:2018 年 03 月 04 日
如果觉得我的文章对你有用,请随意赞赏