C++继承与派生
在继承与派生的学习中,突然有种新的领悟,其实继承与派生也是对派生类数据的新的封装,只是有些数据从基类继承而来,有的自己重新定义。
是不让基类的数据和函数浪费,重新复用。继承不是简单的将基类数据挪到相关的public protected private下,因为派生类无论何种继承,都无法访问基类的private数据。
继承与派生仅限于成员属性,其余保持不变,如const或者static修饰。
言归正传,进入新的学习章节:
继承与派生解决了传统代码中的数据和函数复用问题。
在C++中一个新类可以从已有类中获得其操作和数据结构。
新类被称为子类或者派生类,被继承的类则被称为:父类或者基类。派生类可以有一个父类->单一继承。
也可以有多个父类->多重继承。
class 派生类:继承方式 基类
{
public:
A 可以是新定义的成员,也可以是父类中已存在改写的成员。同名即覆盖或者称为隐藏。无论函数传入形参如何
private:
B
protected:
C
}
继承方式有三种,public继承,private继承,protected继承,默认为private继承。
基类的构造函数和析构函数不在继承范围之内,也就是说除了析构和构造函数外,子类继承全部的父类成员。
在子类中如果声明了一个跟父类中函数相同的成员时,则父类的该函数在继承过程中被覆盖。
既然派生类中包含了自己定义的新成员和从基类中继承的成员,则权限如何定义呢:
继承方式中有个小口诀:public属性的可以被类外访问,protected的可以被派生类访问,private的只能被类自己本身和友元访问。
public继承:
基类中成员属性为public和protected的,在派生类中属性保持不变,且可访问,基类private的成员在派生类中不可访问,
如果要想访问只能通过基类的public属性的函数来访问。
public继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:public, protected, private。
protected继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:protected, protected, private
private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private, private, private
总结起来一句话:类外只有public继承的public属性成员可以访问,类内所有继承方式的private都不可以访问。
派生类的构造和析构函数:
单一派生类:
构造函数:先执行基类,后执行派生类。
析构函数:先执行派生类,后执行基类。
如果派生类数据成员中有对象数据成员,必须使用参数列表。放在基类初始化后边。
复杂派生类:
复杂派生类指的是有多个基类继承,基类的执行顺序就是定义的顺序,析构的顺序刚好相反。
派生继承的二义性:
如果派生类中有两个基类,而且基类中都有相同的元素,则在调用时要加上类的限定符::加以限定域,但增加了编程的复杂度。
如果派生类有多个基类,而这些基类都有一个共同的基类,则派生类的最终数据中,会有多份共同基类的同名成员,调用需要加限定符,
C++中提供了虚基类,就是继承有共同基类时,可以用class 派生类名:virtual 继承方式 基类名。
这个基类被称为虚基类,虚基类对紧跟其后的类起作用,默认为私有继承。
这种继承方式也是被称为虚继承。
为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。
这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。
继承派生的构造函数执行顺序:
首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;
执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;
执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;
执行派生类自己的构造函数;
析构以与构造相反的顺序执行;
在继承派生中,如果有私有数据,而且基类有显性构造函数,则派生类也必须写显性构造函数
二义性:
#include
using namespace std;
class base
{
public:
void print(){cout<<"base print"<
base(){cout<<"base construct"<
private:
};
class mid1 :public base
{
public:
mid1(){cout<<"mid1";}
};
class mid2 :public base
{
public:
mid2(){cout<<"mid2";}
};
class CTest:public mid1,public mid2
{
public:
CTest(){cout<<"Ctest";}
};
int main(void)
{
CTest ss;
//ss.print();
ss.mid1::print();
ss.mid2::print();
return 0;
}
虚继承:虚继承的目的是在继承过程中使共同基类只保留一份数据成员。
#include
using namespace std;
class base
{
public:
void print(){cout<<"base print"<
base(){cout<<"base construct"<
private:
};
class mid1 : virtual public base
{
public:
mid1(){cout<<"mid1";}
};
class mid2 :virtual public base
{
public:
mid2(){cout<<"mid2";}
};
class CTest:public mid1,public mid2
{
public:
CTest(){cout<<"Ctest";}
};
int main(void)
{
CTest ss;
ss.print();
ss.mid1::print();
ss.mid2::print();
return 0;
}
阅读(1938) | 评论(0) | 转发(0) |