继承性是面对对象程序设计中最重要的特征之一它允许在既有类的基础上创建新类,并可以根据所面对问题的不同情况对新类进行更具体,更详细的说明与操作。
通过代码看基类与派生类
class A //基类
{
public:
int _pub;
protected:
int _pro;
private:
int _pri;
};
class B: protected A // 派生类 B类 保护继承 A类
// class B:public A 公有继承
// class B:private A 私有继承
{
public:
int pub;
protected:
int pro;
private:
int pri;
};
在不同继承下,派生类中基类成员的访问属性
此图可以看出:无论哪种继承方式,派生类新定义成员均不能直接访问基类的私有成员,只能通过基类的公有成员函数来访问私有成员,当只有一次继承时,保护继承和私有继承没有本质区别,在多次继承的情况下,保护继承可以进一步将基类成员传递给派生类的派生类,而私有继承不可以
继承下构造函数与析构函数调用规则
一:构造函数不为缺省构造时:
class A
{
public:
A()
{
cout << "A ()" << endl;
}
~A()
{
cout << "~A ()" << endl;
}
int _pub;
protected:
int _pro;
private:
int _pri;
};
class B: public A
{
public:
int pub;
B()
{
cout << "B ()" << endl;
}
~B()
{
cout << "~B ()" << endl;
}
protected:
int pro;
private:
int pri;
};
int main()
{
B b; //创建派生类对象
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
}
从结论可以看出,在***创建派生类对象时,先调用B 的构造函数,在B 构造函数的初始化列表阶段调用了基类A的构造函数,再回到B的构造对对象进行初始化。析构时先调用派生类,再调用基类。***
二:基类定义具有形参的构造函数
class A
{
public:
A(int a =10 )
:_pri (a)
{
cout << _pri << endl;
cout << "A ()" << endl;
}
~A()
{
cout << "~A ()" << endl;
}
int _pub;
protected:
int _pro;
private:
int _pri;
};
class B: public A
{
public:
int pub;
B(int a= 100,int b=200)
:A(a)
, pri(b)
{
cout << pri << endl;
cout << "B ()" << endl;
}
~B()
{
cout << "~B ()" << endl;
}
protected:
int pro;
private:
int pri;
};
int main()
{
B b;
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
}
当基类定义了具有形参的构造函数,派生类也必须定构造函数,提供将形参传递给基类构造函数的途径,使基类对象在进行初始化时可以得到相关数据
同名隐藏:
class A
{ public:
int a;
};
class B :public A
{ public:
int a;
};
当创建B的对象b去调用a时,只会去调用派生类的 成员,并且与a成员的类型无关
多继承:
class C:public A ,public B //class C:public A , B (默认私有继承B)
{
public:
int c_pub;
private:
int c_pri;
};
多继承下的菱形继承
存在二义性问题:创建C对象直接调用a时,不知道调用B1的成员B2的成员
以下调用正确:
c.B1::a;
c.B2::a;
虚拟继承:
class B : virtual public A
在内存中存放:
在派生类中只保留了一个副本,也成功解决了二义性问题。