关于继承与派生的小结

  你们学了C++以后都知道C++是一种面向对象的语言,所以,面向对象程序设计的主要特征也是C++的主要特色,具体以下:
ide

 1.封装性:所谓封装性就是将一组数据与这组数据有关的操做集合组装在一块儿,造成一个能动的实体,也就是对象。C++中经过创建类这个数据类型来支持封装性。函数

 2.继承性:继承性是指一个类具备另外一个类的属性和行为。这个类既具备另外一个类的所有特征,又具备自身的独有特征。C++中将其称为派生类(或子类),而将其所继承的类称为基类(或父类)。this

 3.多态性:多态性是指不一样的对象调用相同名称的函数,并可致使彻底不一样的行为。C++中的多态性经过使用函数重载、模板和虚函数等概念来实现。spa

  经过以上简单的介绍,相信你们对C++的三大特性也有了简单的了解,下面着重介绍一下关于继承的一些小结。设计

 (1)继承分为单继承、多继承和菱形继承:看下面的图你们会一目了然的。3d


  wKioL1cIl1zgvObfAAAgRy1S3BY845.png

wKioL1cItm7hZSHrAAAen5C1TsI947.png


菱形继承:
指针

class B
{
public:
	int data1;
};

class B1: public B
{
public:
	int data2;
};

class B2: public B
{
public:
	int data3;
};

class D:public B1, public B2
{
public:
	int data4;
};

有上述代码分析可知:B1和B2都继承了B,因此D中就有两份B。这样形成了main()函数在调用时不知道该调用哪个B,即形成了二义性。同时也形成了数据冗余。如何解决这个问题呢?下面引入了虚继承。调试

(2)虚继承:对象

定义格式:
blog

class 派生类名:virtual [继承方式] 基类名

class B
{
public:
	int data1;
};

class B1: virtual public B
{
public:
	int data2;
};

class B2: virtual public B
{
public:
	int data3;
};

class D:public B1, public B2
{
public:
	int data4;
};

经过在继承时加上virtual构成虚基类解决了二义性和数据冗余问题。

(3)继承的定义格式:

  class 派生类名:[继承方式] 基类名

  {

    派生类新增长的成员

  };

  继承方式:a.公有继承(public)

        b.保护继承 (protected)

        c.私有继承 (private)

注意:若是没有指定派生方式,默认为私有继承。

下面经过简单的例子来创建派生类:

class Base//基类
{
public:
Base()
{
cout << "Base()  " << this << endl;
}
    ~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Derive : public Base//派生类以公有继承的方式继承基类
{
public:
Derive()
{
cout << "Derive()  " << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
};
int main()
{
cout<<sizeof(Base)<<endl;//12
cout<<sizeof(Derive)<<endl;//24 派生类的sizeof()大小等于(基类大小+派生类大小)
     return 0;
}

(4)继承关系&访问限定符

看下图能够直观的了解访问限定符与继承关系:

wKiom1cIoUaAPAxnAAB3sH1FcD0934.png

wKiom1cIonyyrtnrAABY5DeU20s508.png

总结:

a.为了记忆方便,能够简单的记做:基类中私有成员不可访问,公有继承不变,私有继承私有,保护继承保护。

b.派生类的对象只可访问公有继承方式下基类中的公有成员。派生类的派生类能够访问公有继承方式和保护继承方式下基类中的公有成员和保护成员。

c.在实际运用中通常使用都是public继承,极少场景下才会使用protetced/private继承。

(5)派生类的默认成员函数

 咱们知道类的默认的六个成员函数有:构造函数、拷贝构造函数、析构函数、赋值运算符重载函数、取地址操做符重载函数、const修饰的取地址操做符重载函数。

  在继承关系里面,在派生类中若是没有显示定义这六个成员函数,编译系统则会默认合成这六个默认的成员函数。

经过对以上例子的调试与分析,能够得出继承关系中构造函数与析构函数分别的调用顺序为:

构造函数调用顺序:

wKiom1cIq3jBGzhFAAAzLE8AkFs032.png

析构函数调用顺序:

wKiom1cIrMGjkkeIAAAxdLW_kGI848.png

(6)继承体系中的做用域

a.在继承体系中基类和派生类是两个不一样做用域。

b.子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可使用 基类::基类成员 访问)

c.注意在实际中在继承体系里面最好不要定义同名的成员。

class Base
{
public:
int x;
void Show()
{
cout << "This is Base, x= " << x << endl;
}
};
class Derived :public Base
{
public:
int x;//同名数据成员
void Show()//同名成员函数
{
cout << "This is derived , x= " << x << endl;
}
};
int main()
{
Derived d;
d.x = 5;//使用同名覆盖原则
d.Show();//使用同名覆盖原则
d.Base::x = 67;//使用做用域运算符访问基类成员
d.Base::Show();//使用做用域运算符访问基类成员函数
}

(7)继承与转换--赋值兼容规则--public继承

a.子类对象能够赋值给父类对象(切割/切片)

b.父类对象不能赋值给子类对象

c.父类的指针/引用能够指向子类对象

d.子类的指针/引用不能指向父类对象(能够经过强制类型转换完成)

(8)友元与继承

  友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

若要访问,在派生类中也加友元函数的声明,这样就能够访问了。

(9)继承与静态成员

  基类定义了static成员,则整个继承体系里面只有一个这样的成员。不管派生出多少个子类,都只有一个static成员实例。

相关文章
相关标签/搜索