C++学习之路: 前向申明
引言:
有种特殊情况,当两个类需要相互引用形成一个”环形“引用时,无法先定义使用。 这时候需要用到前向申明
但是前向申明的类不能实例化。
1 #pragma once 2 3 #include "B.h" 4 class A 5 { 6 public: 7 A(); 8 ~A(); 9 10 B b_; 11 };
#pragma once #include "A.h" class B { public: B(); ~B(); A a_; };
两个类互相包含编译的提示错误为:
1 1>------ 已启动生成: 项目: test, 配置: Debug Win32 ------ 2 1> B.cpp 3 1>g:\cpp\代码\test\test\a.h(10): error C2146: 语法错误: 缺少“;”(在标识符“b_”的前面) 4 1>g:\cpp\代码\test\test\a.h(10): error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int 5 1> A.cpp 6 1>g:\cpp\代码\test\test\b.h(9): error C2146: 语法错误: 缺少“;”(在标识符“a_”的前面) 7 1>g:\cpp\代码\test\test\b.h(9): error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int 8 1> 正在生成代码... 9 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
那么什么是前向申明呢?
#pragma once #include "A.h" class A; //前向申明 class B { public: B(); ~B(); A a_; //不可实例化 };
这样仍然是错误的,因为前向申明是不可实例化的。
编译提示:
1>------ 已启动生成: 项目: test, 配置: Debug Win32 ------ 1> B.cpp 1>g:\cpp\代码\test\test\a.h(10): error C2146: 语法错误: 缺少“;”(在标识符“b_”的前面) 1>g:\cpp\代码\test\test\a.h(10): error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int 1> A.cpp 1>g:\cpp\代码\test\test\b.h(11): error C2079: “B::a_”使用未定义的 class“A” 1> 正在生成代码... ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
很简单的处理,只需要使用指针即可。 经过试验 引用也可。
1 #pragma once 2 #include "A.h" 3 4 class A; 5 class B 6 { 7 public: 8 B(); 9 ~B(); 10 11 A *a_; 12 };
嵌套类:Demo
1 #include <iostream> 2 using namespace std; 3 4 5 class Outer 6 { 7 class Inner 8 { 9 public: 10 void fun() 11 { 12 cout << "Inner:Fun...." << endl; 13 } 14 }; 15 16 public: 17 Inner obj_; 18 void fun() 19 { 20 cout << "Outer:fun..." << endl; 21 obj_.fun(); 22 } 23 24 }; 25 26 int main(void) 27 { 28 Outer o; 29 o.fun(); 30 }
## 从作用域的角度看,嵌套类被影藏在外围类中,该类名只能在外围类中使用。如果在外围类的作用域中使用该类名时,需要加名字限定;
##嵌套类中的成员函数可以再它的类体外定义;
##嵌套类的成员函数对外围类的的成员没有访问权,反之亦然。
##嵌套类仅仅是语法上的嵌入
1 #include <iostream> 2 using namespace std; 3 4 5 class Outer 6 { 7 class Inner 8 { 9 public: 10 void fun(); 11 }; 12 13 public: 14 Inner obj_; 15 void fun() 16 { 17 cout << "Outer:fun..." << endl; 18 obj_.fun(); 19 } 20 21 }; 22 void Outer::Inner::fun() 23 { 24 cout << "Inner:Fun...." << endl; 25 } 26 27 int main(void) 28 { 29 Outer o; 30 o.fun(); 31 }
类体外申明只需要记住要加多个类名即可。