在一个类内部定义一个类,这个类被称之为嵌套类,或嵌套类型。之所以引用嵌套类,往往是因为外围类需要嵌套类对象作为底层实现,并且嵌套类只用于该外围类的实现,同时可以对用户隐藏该底层实现。
嵌套类是一个单独的类,它和外围类是相互独立的,它不具备外围类所定义的成员,同样外围类也不具备嵌套类所定义的成员
同样,外围类对嵌套类没有特别的访问权限,嵌套类对外围了也没有特别的访问权限。friend友元关系也不可以传递
class Base
{
public:
Base(){cout<<"Base\n"<<endl;}
private:
friend class Friend;
int b;
public:
class Nest{
public:
Nest(){cout<<"Nest\n"<<endl;
}
private:
int a;
};
};
class Friend
{
public:
void friendtest();
};
void Friend::friendtest()
{
Base base;
base.b=11;
Base::Nest nest;
nest.a=10;/*无法访问private成员*/
}
对于嵌套类的使用就当成一个类型定义,使用该类型定义一个对象即Base::Nest 与在类内用typedef定义的类型一样.
嵌套类定义时内部可以直接引用外围类的static变量,类型(typedef定义的),枚举类型即使是private
静态成员变量无论是在嵌套类前面声明或者后面声明都可以引用
类型和enum类型必须在嵌套类定义才可以使用
class Base
{
public:
Base(){cout<<"Base\n"<<endl;}
private:
enum Color{RED,BLACK};
typedef char* pchar;
public:
class Nest{
public:
Nest():a(b){cout<<"Nest\n"<<endl;
cout<<"Nest::a="<<a<<endl;
co=RED;
}
int a;
Color co;
pchar pp;
};
Nest P; /*定义了嵌套类对象 若未定义其不会构造嵌套类*/
private:
static int b;
};
int Base::b=1;
void main()
{
Base B;
}
输出结果为
Nest
Nest::a=1
Base
为什么是先构造Nest呢?涉及到构造过程
EffectiveC++条款12:尽量使用初始化而不要在构造函数里赋值
指出:对象的创建分两步:
1. 数据成员初始化。
2. 执行被调用构造函数体内的动作。
构造函数的初始化列表属于第一步,若并未给予赋值则调用对数据成员默认初始化,类数据成员会调用默认构造函数。上述代码中定义了Nest类型的数据成员P,因此会调用Nest默认构造函数。Base的函数体是最后执行的,因此Nest在Base之前输出。
在类外部定义嵌套类,与一般的类定义没什么区别,加了一个作用域限定符
template <typename T>
class Base
{
public:
Base(){cout<<"Base\n"<<endl;}
private:
T a;
class Nest; /*前向声明 不完全类型*/
Nest *p;
};
template<typename T>
class Base<T>::Nest{
public:
Nest(const T&t):b(t){cout<<"Nest\n"<<endl;}
private:
T b;
static int c;
};
template<typename T> int Base<T>::Nest::c=10;
模版
外围类是一个模板,则嵌套类也隐含是模板,其模板形参与外围类相同
实例化外围模板时并不会自动实例化类模板的嵌套类。像任何成员一样,只有当在需要完整类类型的情况下使用嵌套类本身的时候,才会实例化嵌套类
template <typename T>
class Base
{
public:
Base(){cout<<"Base\n"<<endl;}
private:
T a;
class Nest{
public:
Nest(const T&t):b(t){cout<<"Nest\n"<<endl;}
private:
T b;
static int c;
};
Nest *p;
};
template<typename T> int Base<T>::Nest::c=10;
上述代码中若将Base实例化Base<int> B;并不会实例化嵌套类Nest,因为Base里的对象Nest是一个指针,只有当对其解引用是才会实例化Nest<int>
继承
三种访问权限
public:可以被任意实体访问
protected:只允许子类及本类的成员函数访问
private:只允许本类的成员函数访问
继承的访问权限
1、public继承不改变基类成员的访问权限
2、private继承使得基类所有成员在子类中的访问权限变为private
3、 protected继承将基类中public成员变为子类的protected成员,其它成员的访问权限不变。
4、基类中的private成员不受继承方式的影响,子类永远无权访问。
由于嵌套类跟外围类是个相对独立的类,基类无法访问嵌套类的protected的成员,自然基类的派生类也无法访问,但嵌套类可以被继承
#include <iostream>
using namespace std;
template <typename T>
class Base
{
public:
Base(){cout<<"Base\n"<<endl;}
protected:
T a;
class Nest;/*前向声明 不完全类型*/
Nest *p;
};
template<typename T>
class Base<T>::Nest{
public:
Nest(const T&t):b(t){cout<<"Nest\n"<<endl;}
protected:
void nestdisplay(){cout<<"nestdisplay b="<<b<<endl;}
private:
T b;
static int c;
};
template<typename T> int Base<T>::Nest::c=10;
template <typename T>
class Derived:public Base<T>
{
public:
Derived(){cout<<"derived\n"<<endl;}
void derivedtest(T& a);
private:
int d;
};
template <typename T>
void Derived<T>::derivedtest( T& a)
{
p=new Nest(a);
p->nestdisplay();/*若将其nestdisplay声明为protected 则Derived继承类无法访问nestdisplay成员函数*/
delete p;
}
void main()
{
Derived<int> D;
int a=3;
D.derivedtest(a);
}
局部类与嵌套类的区别,一般很少用局部类
见http://www.cnblogs.com/charley_yang/archive/2011/04/05/2005897.html