内部类
在C++中允许在类内部定义类,这样的类称为内部类,这个内部类所在的类称为外部类。内部类可以作为外部类的基础,外部类在内部类基础上扩充新的功能并且不会相互影响。
定义内部类的语法形式如下所示:
class 外部类名
{
外部类成员;
访问限定符:
class 内部类名
{
内部类成员
};
};
下面按照内部类定义形式,在外部类Outer中定义了内部类Inner,代码如下所示:
class Outer
{
public:
class Inner //定义内部类
{
public:
//定义内部类构造函数
Inner() { inner_n = 10; }
//定义内部类show()函数
void show() { cout << "inner_n = " << inner_n << endl; }
private:
int inner_n; //内部类私有数据成员
}; //内部类定义结束
//定义外部类构造函数
Outer() { outer_n = 100; }
void show() { cout << "outer_n = " << outer_n << endl; }
private:
int outer_n;
};
上述代码中定义了类Outer的内部类Inner,内部类的定义形式和普通类的定义形式相同。代码中内部类和外部类没有交互,只是通过内部类又划定了一个名字空间。
一个内部类对象可以访问创建它的外部类对象的内容,包括私有变量。要想实现这个特性,内部类对象就必须有指向外部类对象的引用。
接下来通过一个案例来学习内部类访问外部类的方法,如例1所示。
例1
1 #include <iostream>
2 using namespace std;
3
4 class Outer //定义外部类Outer
5 {
6 public:
7 class Inner{ //定义内部类Inner
8 private:
9 int inner_n;
10 public:
11 //内部类成员函数set_outer_n()通过外部类引用参数访问外部类私有成员outer_n
12 void set_outer_n(Outer &ref_outer) { ref_outer.outer_n = 10; }
13 void set_inner_n() { inner_n = 100; }
14 //内部类成员函数show()通过外部类引用参数访问外部类成员函数show()
15 void show(Outer &ref_outer)
16 {
17 ref_outer.show();
18 cout << "inner_n = " << inner_n << endl;
19 }
20 }; //内部类定义结束
21 //Inner inner_obj; //定义内部类对象inner
22 //外部类成员函数
23 void show() { cout << "outer_n = " << outer_n << endl; }
24 private:
25 int outer_n;
26 };
27
28 int main()
29 {
30 Outer outer_obj; //定义外部类对象
31 Outer::Inner inner_obj; //使用作用域限定符定义内部类对象
32
33 inner_obj.set_inner_n(); //调用内部类函数set_inner_n()
34 inner_obj.set_outer_n(outer_obj); //调用内部类函数set_outer_n()
35 inner_obj.show(outer_obj); //调用内部类函数show()
36
37 system("pause");
38 return 0;
39 }
程序运行结果如图1所示。
图1 例1运行结果
例1中定义了类Outer及其内部类Inner,在内部类中访问了外部类的数据成员outer_n和成员函数show(),需要注意的是在内部类中通过使用外部类对象的引用访问了外部类成员。
例1中定义的内部类具有public属性,因此才能在外部访问内部类,定义内部类对象,如代码第31行,若将内部类的属性设置为private,则编译时出错,提示内容如图1所示。
图1 编译错误提示
定义了内部类后,不必在类外部定义内部类对象,而可以直接在外部类内定义内部类对象。在例3-23添加代码21行内容,修改main()函数为下述内容:
int main()
{
Outer outer_obj; //定义外部类对象
outer_obj.inner_obj.set_inner_n(); //调用内部类函数set_inner_n()
outer_obj.inner_obj.set_outer_n(outer_obj); //调用内部类函数set_outer_n()
outer_obj.inner_obj.show(outer_obj); //调用内部类函数show()
system("pause");
return 0;
}
重新运行程序,运行结果与例1运行结果相同。
接下来看一个比较复杂的案例,来体会内部类的应用优势,如例2所示。
例2
1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 struct IBase //接口IBase
6 {
7 virtual void base() = 0; //声明纯虚函数base()
8 };
9
10 struct IDerive1:public IBase //接口IDerive1
11 {
12 virtual void derive1() = 0; //声明纯虚函数derive1()
13 virtual void base() = 0; //声明纯虚函数base()
14 };
15
16 struct IDerive2:public IBase //接口IDerive2
17 {
18 virtual void derive2() = 0; //声明纯虚函数derive2()
19 virtual void base() = 0; //声明纯虚函数base()
20 };
21
22 void callderive1(IDerive1 &p) //定义函数callderive1()
23 {
24 p.derive1();
25 p.base();
26 }
27
28 void callderive2(IDerive2 &p) //定义函数callderive2()
29 {
30 p.derive2();
31 p.base();
32 }
33
34 class COuter:public IDerive1{ //定义外部类继承自IDerive1
35 private:
36 //外部类的私有变量
37 string outer_private; //定义外部类私有变量
38
39 class CInner:public IDerive2{ //定义内部类,继承自IDerive2
40 private:
41 //定义外部类指针作为内部类成员,用于操作外部类
42 COuter *parent;
43 public:
44 CInner(COuter *p):parent(p)
45 {
46 }
47 //重写基类IDerive2的虚函数,访问了外部类的私有成员
48 void derive2()
49 {
50 cout << "derive2 called for inner of " << parent-> outer_private << endl;
51 }
52 //重写基类IDerive2的虚函数,虽然与外部类成员函数同名,但无歧义
53 void base()
54 {
55 cout << "base called for inner" << endl;
56 }
57 };
58 CInner inner;
59 public:
60 //定义外部类构造函数
61 COuter(const string &str):outer_private (str), inner(this){}
62 //重写基类IDerive1中的虚函数derive1()
63 void derive1()
64 {
65 cout << "derive1 called for outer" << endl;
66 }
67 //重写基类IDerive1中的虚函数base()
68 void base()
69 {
70 cout << "base called for outer" << endl;
71 }
72 //重载IDerive2&引用
73 operator IDerive2&()
74 {
75 return inner;
76 }
77 };
78 int main()
79 {
80 COuter obj("outer");
81 callderive1(obj);
82 callderive2(obj);
83 system("pause");
84 return 0;
85 }
程序运行结果如图2所示。
图2 例2运行结果
例2中定义了抽象基类IBase以及两个派生抽象类IDerive1、IDerive2。函数callderive1()和callderive2()分别以类IDerive1、IDerive2的引用为参数实现了函数调用。外部类COuter及内部类CInner分别继承自IDerive1、IDerive2,并重写了base()、derive1()、derive2(),从代码中看到内部类通过外部类指针访问了外部类的私有成员。
从上例可以看出,在面向对象程序设计中,内部类是用来描述、组织和控制软件系统中对象关系的一种高级形式。内部类能够访问外部类的成员,为外部类扩展了功能和接口,但并没有增加外部类的public方法,能够很好地实现代码隐藏。另外,由于内部类和外部类位于不同的名字空间中,因此能够消除多重继承中存在的二义性问题。