C++继承(二)派生类的默认函数

来源:互联网 发布:加州101电台知乎 编辑:程序博客网 时间:2024/06/05 05:58

我们在学习类的时候知道类中有6个默认函数,那么我们在继承中,是继承基类中的所有成员,那就也包括他们的默认函数,so,派生类中也有它的6个默认函数。

这里写图片描述

1、构造函数与析构函数

单继承:

构造函数不同于其他类的方法,应为它创建新的对象,要调用基类中的私有成员,因为派生类不能直接访问基类的私有成员,必须要调用基类方法进行访问,而其他类仅仅是被现有的对象调用而已,所以构造函数不能被继承;
继承以为这派生类可以使用基类中的方法,然而在构造函数之前,并没有对象来操作;
so:我们来看看下段代码:

class Base{public:    Base(int a = 0, int b = 1, int c = 2)        : _pub(a)        , _pro(b)        , _pri(c)    {        cout << "Base::Base()" << endl;    }    ~Base()    {        cout << "Base::~Base()" << endl;    }    int _pub;protected:    int _pro;private:    int _pri;};class Derive : public Base{public:    Derive()    {        cout << "Derive::Derive()" << endl;    }    ~Derive()    {        cout << "Derive::~Derive()" << endl;    }    int pub;protected:    int pro;private:    int pri;};int main(){    Derive d;    return 0;}

这里写图片描述
从这个汇编图上我们可以看到,在调用派生类的构造函数之前有一条命令叫做call Base::Base();所以显示的构造函数的结果是:
这里写图片描述
基类的构造函数先被调用,后面时派生类的构造函数;但是,好多人看看结果就觉得其实是先调用的是基类的构造函数,后面调用的是派生类的构造函数,其实,在main函数中,先调用的是派生类的构造函数,基类的构造函数是在派生类的初始化列表中调用的;千万不要记错,我看好多人都觉得是main函数直接调用的是基类的构造函数

析构函数:

这里写图片描述
析构函数和原来类中的没区别,因为在栈上面创建的所以按照栈上的先进后出的特性,先创建得后析构,后创建的先析构。

多继承:

class Base1{public:    Base1(int a = 0, int b = 1, int c = 2)        : _pub(a)        , _pro(b)        , _pri(c)    {        cout << "Base1::Base1()" << endl;    }    ~Base1()    {        cout << "Base1::~Base1()" << endl;    }    int _pub;protected:    int _pro;private:    int _pri;};class Base2{public:    Base2()    {        cout << "Base2::Base2()" << endl;    }    ~Base2()    {        cout << "Base2::~Base2()" << endl;    }};class Derive : public Base1, public Base2{public:    Derive()    {        cout << "Derive::Derive()" << endl;    }    ~Derive()    {        cout << "Derive::~Derive()" << endl;    }    int pub;protected:    int pro;private:    int pri;};int main(){    Derive d;    return 0;}

这里写图片描述
从结果来看,多继承也是先调用的基类的构造函数,但是,多继承中基类调用顺序是:派生类的函数先调用,在上面代码中Base1是先被调用的。在多继承中也是在派生类的构造函数初始化列表中调用的基类的构造函数,按照先声明的先调用;

析构函数不变;

2、拷贝构造函数

1、将新的对象初始化为一个同类对象
2、按值将对象传递给函数
3、函数按值返回对象
4、编译器生成临时对象
如果程序没有显式定义拷贝构造函数,,编译器将自动生成一个。
当然,如果想在派生类中构造基类对象,那么不仅仅可以用构造函数,也可以用拷贝构造函数;

class Base{public:    Base(int a = 0, int b = 1, int c = 2)        : _pub(a)        , _pro(b)        , _pri(c)    {        cout << "Base::Base()" << endl;    }    ~Base()    {        cout << "Base::~Base()" << endl;    }    int _pub;protected:    int _pro;private:    int _pri;};class Derive:public Base{public:    Derive(const Base& d)        : Base(d)//拷贝构造函数    {        cout << "Derive::Derive()" << endl;    }    ~Derive()    {        cout << "~Derive::~Derive()" << endl;    }public:    int d_pub;protected:    int d_pro;private:    int d_pri;};int main(){    Base b(1, 2, 3);    Derive a(b);    return 0;}

程序的结果:
这里写图片描述

这里我们没有给出基类的拷贝构造函数,但是基类在析构函数中多了一个基类的析构函数,就说明编译器中自动给基类生成了一个拷贝构造函数,因为在基类中我没有定义指针成员,浅拷贝就可以满足,如果在基类中定义了指针变量,必须进行显式拷贝构造函数,即进行深拷贝。不然就会对一块空间析构两次。

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

必须是在public继承下:

1、子类对象可以赋值给父类对象
2、父类对象不能赋值给子类对象
3、父类的指针/引用可以指向子类对象
4、子类的指针/引用不能指向父类对象(可以通过强制类型转换)

class Base{public:    Base(int a = 0, int b = 1, int c = 2)        : _pub(a)        , _pro(b)        , _pri(c)    {        cout << "Base::Base()" << endl;    }    ~Base()    {        cout << "Base::~Base()" << endl;    }    int _pub;protected:    int _pro;private:    int _pri;};class Derive :public Base{public:    Derive()    {        cout << "Derive::Derive()" << endl;    }    ~Derive()    {        cout << "~Derive::~Derive()" << endl;    }public:    int d_pub;protected:    int d_pro;private:    int d_pri;};void FunTest(const Base& d){}void FunTest1(const Derive& d){}int main(){    Derive d;    Base b(0, 0, 0);    b = d;//子类赋值给父类 可以    d = b;//父类赋值给子类 不可以    FunTest(b);    FunTest(d);    FunTest1(b); //子类的指针引用不能指向父类的对象  错误    FunTest1(d);    Base* pBase = &d;    Derive* pDerive = &b; //不可以,两个不是一个能行    Derive* pDerive = (Derive*)&b; //访问可能会越界,崩溃}

图解:
这里写图片描述

0 0
原创粉丝点击