zoukankan      html  css  js  c++  java
  • C++继承的构造与析构!

    赋值兼容性原则:子类就是特殊的父类

    ①子类对象可以当作父类对象使用,②子类对象可以直接赋值给父类对象,③子类对象可以直接初始化父类对象,④父类指针可以直接指向子类对象,⑤父类引用可以直接引用子类对象。

    #include <iostream>
    
    using namespace std;
    
    class Parent
    {
    protected:
        char* name;
    public:
        Parent()
        {
            name = "Parent";
        }
        void print()
        {
            cout<<"Name:"<<name<<endl;
        }
    };
    class Child:public Parent
    {
    protected:
        int i;
    public:
        Child(int i)
        {
            this->name = "Child";
            this->i = i;
        }
    };
    int main()
    {
        Child child(100);
        Parent parent = child;//子类对象可以直接赋值给父类对象
        Parent* pp = &child;  //父类指针可以直接指向子类对象
        Parent& rp = child;  //父类引用可以直接引用子类对象
        parent.print();
        pp->print();
        rp.print();
        return 0;
    }
    View Code

    输出结果:

    继承对象模型:

    类在C++编译器的内部可以理解为结构体,子类是由父类成员叠加子类新成员得到的。

    问题来了,如何初始化父类成员?父类和子类的构造函数有什么关系?

    在子类对象构造的时候需要调用父类构造函数,对其继承来的成员进行初始化。

    在子类对象析构的时候需要调用父类析构函数对其继承来的成员进行清理

    简单的一个例子:

    #include <iostream>
    
    using namespace std;
    
    class Parent
    {
    public:
        Parent()
        {
            cout<<"Parent()"<<endl;
        }
        ~Parent()
        {
            cout<<"~Parent()"<<endl;
        }
    };
    class Child:public Parent
    {
    public:
        Child()
        {
            cout<<"child()"<<endl;
        }
        ~Child()
        {
            cout<<"~child()"<<endl;
        }
    };
    void run()
    {
        Child child;
    }
    int main()
    {
        run();
        return 0;
    }
    View Code

    输出结果为:

    ①子类对象在创建的时候首先自动调用父类的构造函数,父类构造函数执行结束后,执行子类的构造函数,

    ②当父类的构造函数有参数时,需要在子类的初始化列表中显示调用。

    将上个例子修改一下:

    #include <iostream>
    
    using namespace std;
    
    class Parent
    {
    public:
        Parent(const char* s)
        {
            cout<<"Parent()"<<endl;
            cout<<s<<endl;
        }
        ~Parent()
        {
            cout<<"~Parent()"<<endl;
        }
    };
    class Child:public Parent
    {
    public:
        Child():Parent("Parameter from Child!")
        {
            cout<<"Child()"<<endl;
        }
        ~Child()
        {
            cout<<"~Child()"<<endl;
        }
    };
    void run()
    {
        Child child;
    }
    int main()
    {
        run();
        return 0;
    }
    View Code

    输出结果为:

    如果一个类继承自并且有其它的对象作为成员,那么构造函数如何调用?口诀:先父母,后客人,再自己。

    #include <iostream>
    
    using namespace std;
    
    class Object
    {
    public:
        Object(const char* s)
        {
            cout<<"Object()"<<" "<<s<<endl;
        }
        ~Object()
        {
            cout<<"~Object()"<<endl;
        }
    };
    class Parent : public Object
    {
    public:
        Parent(const char* s):Object(s)
        {
            cout<<"Parent()"<<endl;
            cout<<s<<endl;
        }
        ~Parent()
        {
            cout<<"~Parent()"<<endl;
        }
    };
    class Child:public Parent
    {
    protected:
        Object o1;
        Object o2;
    public:
        Child():o2("o2"),o1("o1"),Parent("Parameter from Child!")
        {
            cout<<"Child()"<<endl;
        }
        ~Child()
        {
            cout<<"~Child()"<<endl;
        }
    };
    void run()
    {
        Child child;
    }
    int main()
    {
        run();
        return 0;
    }
    View Code

    输出:

    同名成员变量:当子类中定义的成员变量与父类中的成员变量同名时会发生什么?

    子类依然从父类继承同名成员,只是通过作用域分别符::进行同名成员区分,对于机器来说它们只是存储在不同位置的变量,对于人来说看起来是同名的。

    懒惰不会让你一下子跌到 但会在不知不觉中减少你的收获; 勤奋也不会让你一夜成功 但会在不知不觉中积累你的成果 越努力,越幸运。
  • 相关阅读:
    快速排序和归并排序的迭代实现
    Longest Increasing Subsequence Review
    IOCCC 1987 最佳单行代码解读
    C++类的成员函数对应的链接器符号的解析
    Scalable Global ID Generator Design
    欧拉回路 (Euler Circuit) POJ 1780
    深入理解函数内静态局部变量初始化
    memcached 线程模型
    类的加载与ClassLoader的理解
    字符集常见码表说明
  • 原文地址:https://www.cnblogs.com/Rainingday/p/7577641.html
Copyright © 2011-2022 走看看