• C++学习(c++17)——父类和构造函数、析构函数


    最近主课蛮繁重的,再加上刚好复习到类和对象的基础,没有太多需要reStudy的,所以没怎么记博客。今天看到了对父类的利用,感觉这块一直是模模糊糊的,还是得记一下。



    LeoRanbom的博客

    原帖地址https://www.cnblogs.com/ranbom/

    博主LeoRanbom

    只在原帖地址的博客上发布,其他地方看到均为爬取。

    如果觉得不错希望来点个赞。


    父类和构造函数

    ​ 在创建对象的时候,会同时创建父类和包含在其中的对象。

    执行的顺序大概如下:

    1. 先执行父类构造函数
    2. 再执行数据成员对象的构造函数
    3. 最后执行该类本身的构造函数。

    但实践出真知嘛,还是敲一敲比较深刻。

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<random>
    #include<chrono>
    using namespace std;
    
    class Something{
    public:
        Something() { cout << 2; }
    };
    
    class Based {
    public:
        Based() {
            cout << 1;
        }
    };
    class Derived : public Based {
    public:
        Derived() { cout << 3; }
    private:
        Something mSomething;
    };
    int main() {
        Derived derived;
    }
    

    结果输出123。符合。

    如果父类构造函数有参数,那么可以在子类构造函数旁用初始化器来链接构造函数。

    看到这里我小小的脑袋就有了大大的疑惑了——不是先执行父类构造函数么?那子类构造函数传给父类的初始化器有用么?书上也没有写,还是敲一下。

    class Something{
    public:
        Something() { cout << 2; }
    };
    
    class Based {
    public:
        Based(int i) {
            cout << i;
        }
    };
    class Derived : public Based {
    public:
        Derived():Based(7){ cout << 3; }
    private:
        Something mSomething;
    };
    int main() {
        Derived derived;
    }
    
    

    如上,我把父类Based的构造函数改为有参构造函数,然后在子类Derived的构造函数中使用初始化器给父类Based传参。输出的结果是723。好吧,大概懂了它是怎样一个输出规律。

    父类调用子类重写的方法

    又有新的疑惑了,试试。

    普通的重写&虚方法

    class Something{
    public:
        Something() { cout << 2; }
    };
    
    class Based {
    public:
        Based() {
            pushout();
        }
        void pushout() { cout << 'a'; }
    };
    class Derived : public Based {
    public:
        Derived() { pushout(); }
        void pushout() { cout << 'b'; }
    private:
        Something mSomething;
    };
    int main() {
        Derived derived;//Based* ptr = new Derived同样的效果,输出a2b
    }
    

    输出a2b,即创建子类对象时会调用父类的构造函数,构造函数中会执行父类的方法。

    如果改成虚方法呢?

    试了一下,同样输出a2b。也就是无论是普通方法重写或者虚方法重写,它都会调用父类的方法。

    如果子类没有重写,则输出父类的方法。a2a

    手贱试了一下将构造 函数virtual,编译报错提示构造函数只允许inline型。

    父类和析构函数

    先扔顺序:

    1. 该类的析构函数
    2. 销毁数据,所以接下来是数据成员的析构函数
    3. 父类析构函数

    与构造函数顺序恰好相反,好记。

    与无法virtual的构造函数恰恰相反,析构函数推荐!建议!最好!加上virtual。

    class Something{
    public:
        Something() { cout << 2; }
        ~Something() { cout << 2; }
    };
    
    class Based {
    public:
         Based() {
             cout << 1;
        }
         ~Based() { cout << 1; }
    };
    class Derived : public Based {
    public:
        Derived() { cout << 3; }
        ~Derived() { cout << 3; }
    private:
        Something mSomething;
    };
    
    int main() {
        Based* ptr = new Derived;
        delete ptr;
    }
    

    这段代码析构函数没有加virtual,最终输出1231,即没有调用子类和数据成员的析构函数,很严重的一个bug。

    而加上后,便输出123321。

    在子类的重写方法中调用父类原本的方法

    直接调用代码没办法运行。查了一下,是因为C++的名称解析规则,先解析局部作用域,再解析 类作用域。所以子类会不停地调用自身,形成无限递归。如果要调用父类的该方法,应该用Based::pushout()来调用。

    查到了Visual C++中支持__super关键字(2个下横杠)

    可以用__super::方法名 来指代父类的方法。(好像java也是这样的?)

  • 相关阅读:
    07.Linux-CentOS系统库文件libaudit.so.1丢失问题
    06.Linux-RedHat系统网卡服务连不上活跃连接路径变化
    05.Linux-CentOS系统普通用户SSH远程问题
    04.Linux-CentOS系统SSH连接问题
    03.Linux-CentOS系统user用户改密码问题
    解决pycharm问题:module 'pip' has no attribute 'main'
    Centos7搭建主从DNS服务器
    docker 启动镜像报 WARNING: IPv4 forwarding is disabled. Networking will not work.
    dockerfile文件命令详解
    Elasticsearch集群搭建笔记(elasticsearch-6.3.0)
  • 原文地址:https://www.cnblogs.com/ranbom/p/12758076.html
Copyright © 2020-2023  润新知