文章目录
1 在类 B 的头文件中声明 类 A 的指针 pA
// A.h 头文件 #pragma once class A { public: void Action(); }; // B.h 头文件 #pragma once <strong>class A;</strong> class B { public: B(A*); private: A *pA; // Ok };
在类 B 的声明头文件中必须前置声明类 A,否则,编译器报:语法错误,标识符 A。
2 在类 B 的头文件中引用类 A 的指针 pA,且在类 B 的第二格构造函数中调用 A::Action 函数
// A.h 头文件 #pragma once class A { public: void Action(); }; // B.h 头文件 #pragma once class A; class B { public: B(A *pa) { pa->Action(); // error } private: A *pA; // Ok };
编译器报错,不知道 A 的定义。
3 在类 B 的头文件中声明类 A 的变量 a
// A.h 头文件 #pragma once class A { public: void Action(); }; // B.h 头文件 #pragma once class A; class B { public: B(A*); private: A *pA; // Ok //A a; // error, 不知道 A 的类型信息,无法求得 B 对象中 a 的具体大小值 };
编译器报错,不知道 A 的定义。
4 在类 B 的头文件中声明类 A 的引用
// A.h 头文件 #pragma once class A { public: void Action(); }; // B.h 头文件 #pragma once class A; class B { public: B(A& ref) : refA(ref) { } private: A &refA; // Ok };
why?
2、3的错误原因是一样的。因为编译器不知道 A 的类型信息,所以不知道 A的具体长度,因此不能分配空间。在编译期,编译器必须知道 A 的大小,才能在构造 A 实例时分配具体大小的空间。注:并非只在创建实例时才必须知道B类型的大小,编译时,也必须知道。
1 、4正确的原因是一样的。因为声明的 A 的指针 pA 或者声明 A 的引用(引用是由指针来实现的),任何类型的指针或引用变量的大小都是确定的,所以编译器可以知道其大小。