• 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration)。下面的程序中,带注释的那行就是类B的前置说明。这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面。如果没有类B的前置说明,下面的程序将不同通过编译,编译器将会给出类似“缺少类型说明符”这样的出错提示。
代码一:
1 #include <iostream> 2 using namespace std; 3 4 class B; // 这是前置声明(Forward declaration) 5 class A { 6 private: 7 B* b; 8 public: 9 A(B* b): b(b) {} 10 }; 11 12 class B { 13 }; 14 15 int main() 16 { 17 B* b = new B(); 18 A* a = new A(b); 19 delete a; 20 delete b; 21 return 0; 22 }
上面程序可以顺利编译和运行(几乎没有做什么,也没有输出)。
代码二:
1 #include <iostream> 2 using namespace std; 3 4 class B; // 这是前置声明(Forward declaration) 5 class A { 6 private: 7 B* b; 8 public: 9 10 A(B* b): b(b) {} 11 void someMethod() 12 { 13 b->someMethod(); // (1) 14 } 15 }; 16 17 class B { 18 public: 19 void someMethod() 20 { 21 cout << "something happened..." << endl; 22 } 23 }; 24 25 int main() 26 { 27 B* b = new B(); 28 A* a = new A(b); 29 a->someMethod(); 30 delete a; 31 delete b; 32 return 0; 33 }
编译发现代码(1)处出错。出错提示往往包括(不同的编译器给出的提示会有所不同):
1. 使用了未定义的类型B;
2. “->somemethod”的左边必须指向类/结构/联合/泛型类型
原因:
1. (1)处使用了类型B的定义,因为调用了类B中的一个成员函数。前置声明class B;仅仅声明了有一个B这样的类型,而并没有给出相关的定义,类B的相关定义,是在类A后面出现的,因此出现了编译错误;
2. 代码一之所以能够通过编译,是因为其中仅仅用到B这个类型,并没有用到类B的定义。
解决办法:
1 #include <iostream> 2 using namespace std; 3 4 class B; // 这是前置声明(Forward declaration) 5 class A { 6 private: 7 B* b; 8 public: 9 A(B* b); 10 void someMethod(); 11 }; 12 13 class B { 14 public: 15 void someMethod(); 16 }; 17 18 A::A(B* b):b(b) 19 { 20 } 21 22 void A::someMethod() 23 { 24 b->someMethod(); 25 } 26 27 void B::someMethod() 28 { 29 cout << "something happened..." << endl; 30 } 31 32 int main() 33 { 34 B* b = new B(); 35 A* a = new A(b); 36 a->someMethod(); 37 elete a; 38 delete b; 39 return 0; 40 }
参考资料