我有一个问题,我认为这与前向声明有关,但也许不是.
这是相关代码:
啊
#ifndef A_H_ #define A_H_ #include "B.h" class A { private: B b; public: A() : b(*this) {} void bar() {} }; #endif /*A_H_*/
BH
#ifndef B_H_ #define B_H_ #include "A.h" class A; class B { private: A& a; public: B(A& a) : a(a) {} void foo() { /*a.bar();*/ } //doesn't compile }; #endif /*B_H_*/
main.cpp中
#include "A.h" int main() { A a; return 0; }
问题似乎是调用A :: bar().程序成功编译,直到我尝试调用此方法,此时我得到两个错误:
错误:无效使用不完整类型'struct A'
错误:'struct A'的前向声明
我认为这是因为A :: bar()尚未定义或声明,因为两个标题相互引用.但是,我转发申报的A级,我不知道还需要做什么.我是C++的新手,所以请原谅我.我无法在网上找到这个问题的答案.一如既往,提前谢谢!
你有一个循环引用,所以你需要分开Bh试试像:
BH:
#ifndef B_H_ #define B_H_ // don't include A.h here! class A; class B { private: A& a; public: B(A& a) : a(a) {} void foo(); }; #endif /*B_H_*/
B.cpp:
#include "B.h" #include "A.h" void B::foo() { a.bar(); } // now you're ok
编辑:解释为什么需要将其拆分为两个文件:
该类B
包含一个引用A
,可以是所谓的不完整类型.你不能调用它上面的任何函数,因为编译器还不知道A
它是什么- 它只知道它是某种类.一旦你包含Ah(在.cpp文件中),那么它A
就是一个完整的类型,你可以用它做任何你喜欢的事情.
您不能将整个事件保存在一个头文件中,因为您将获得循环引用.你阻止了包含守卫的无限循环,但是你得到了一些你不想要的东西.看看编译器在编译main.cpp时最终会遇到什么,就像之前一样:
// #include "A.h" ==> #define A_H_ // #include "B.h" ==> #define B_H_ // #include "A.h" ==> nothing happens! (since A_H_ is already defined) class A; class B { private: A& a; public: B(A& a) : a(a) {} void foo() { a.bar(); } // <-- what the heck is A here? // it's not defined until below }; class A { private: B b; public: A() : b(*this) {} void bar() {} }; int main() { A a; return 0; }