C++面向对象进阶之/ 构造函数在继承中的注意点 / 初始化列表

一、构造函数在继承中的注意点

1.引入

#include <iostream>

using namespace std;

class A {
public:
    A() {
        cout << this << "父类A的 无参数构造函数被调用\n";
    }
};

class B : public A {
public:
    B() {
        cout << this << "父类B的 无参数构造函数被调用\n";
    }
};

int main(int argc, char **argv) {
    B obj_1;
    return 0;
}

在这里插入图片描述
//
为什么父类A中的构造函数被调用呢?

如果父类有private修饰的成员变量,在子类中是无法使用,也就是意味着子类不能够对这些private成员变量进行初始化,因此就需要调用父类的构造函数

//
因此:

创建子类对象时,程序首先调用父类的构造函数,然后再调用子类的构造函数

父类构造函数负责初始化继承的数据成员

子类构造函数主要用于初始化新增的数据成员

子类构造函数总是需要调用一个父类构造函数;当父类没有无参数的构造函数时,就必须显式指明调用哪一个构造函数

2.默认调用父类无参构造函数

#include <iostream>

using namespace std;

class A {
public:
    A() {
        cout << this << "父类A的 无参数构造函数被调用\n";
    }

    A(int temp) {
        cout << this << "父类A的 有参数构造函数被调用\n";
    }
};

class B : public A {
public:
    B() {
        cout << this << "父类B的 无参数构造函数被调用\n";
    }

    B(int temp) {
        cout << this << "父类B的 有参数构造函数被调用\n";
    }
};

int main(int argc, char **argv) {
    B obj_1;
    cout << "---------------\n";
    B obj_2(11);
    return 0;
}

在这里插入图片描述
当父类有无参构造函数,在自动调用 子类构造函数 之前,一定会 先 自动调用父类的无参构造函数

3.父类没有无参构造函数,那么子类必须指定

#include <iostream>

using namespace std;

class A {
public:
//    A() {
//        cout << this << "父类A的 无参数构造函数被调用\n";
//    }

    A(int temp) {
        cout << this << "父类A的 有参数构造函数被调用\n";
    }
};

class B : public A {
public:
    B() {
        cout << this << "父类B的 无参数构造函数被调用\n";
    }

    B(int temp) {
        cout << this << "父类B的 有参数构造函数被调用\n";
    }
};

int main(int argc, char **argv) {
    B obj_1;
    cout << "---------------\n";
    B obj_2(11);
    return 0;
}

加粗样式
子类构造函数中怎样指定调用父类的哪个构造函数?
初始化列表

二、初始化列表

是在构造函数中,一种特殊写法的对成员变量初始化的方式

#include <iostream>

using namespace std;

class Person {
public:
    int age;
    char *address;

//    // 这是普通的写法
//    Person(int age, char *address) {
//        this->age = age;
//        this->address = address;
//    }

    // 使用初始化列表,对成员变量进行设置默认值
    Person(int age, char *address): age(age), address(address){

    }
};


int main(int argc, char **argv) {
    // 创建对象
    Person boy(33, "m78");
    // 获取对象的成员变量
    cout << boy.age << " " << boy.address << "\n";

    return 0;
}

调用父类的构造函数

#include <iostream>

using namespace std;

// 父类
class People {
public:
    char *name;
    int age;

    People(char *name, int age) {
        this->name = name;
        this->age = age;
    }

    virtual void display() {
        cout << this->name << "今年" << this->age << "岁了,是个自由从业者" << endl;
    }

};


// 子类
class Teacher : public People {
public:
    int salary;

    Teacher(char *name, int age, int salary) : People(name, age) {
        this->salary = salary;
    }

    void display() {
        cout << this->name << "今年" << this->age << "岁了,是一名教师,每月有" << this->salary << "元的收入" << endl;
    }
};


int main() {
    People *boy = new People("小明", 23);
    boy->display();
    
    People *girl = new Teacher("菲菲", 35, 8200);
    girl->display();
    return 0;
}

在这里插入图片描述
注意:成员变量的初始化顺序与初始化列表中列出的变量的顺序无关,它只与成员变量在类中定义的先后顺序有关

#include <iostream>

using namespace std;

class Demo {
public:
    int m_a;
    int m_b;

    Demo(int b) : m_b(b), m_a(m_b) {

    }

    void show() {
        cout << this->m_a << ", " << this->m_b << endl;
    }
};


int main() {
    Demo obj(100);
    obj.show();
    return 0;
}

在这里插入图片描述

在这段代码中:
定义了一个名为 Demo 的类,其中有两个 int 类型的成员变量 m_a 和 m_b 。
构造函数 Demo(int b) 接受一个参数 b ,用于初始化成员变量 m_b ,并通过 m_a(m_b) 尝试初始化 m_a 。
需要注意的是,在初始化列表中 m_a(m_b) 的这种初始化方式是不正确的。C++ 中,成员变量的初始化顺序是按照它们在类中的声明顺序进行的,而不是按照初始化列表中的顺序。所以在这里,m_a 会先被初始化(使用默认值),然后再执行 m_a(m_b) ,但这并不是对 m_a 的初始化操作,可能会导致未定义的行为。
在 main 函数中,创建了一个 Demo 类的对象 obj 并传递 100 给构造函数,然后调用 show 方法输出 m_a 和 m_b 的值。由于前面提到的初始化问题,m_a 的值可能不是预期的。

多继承中怎么用?

#include <iostream>

using namespace std;


class A {
public:
    A(int num) {
        cout << "A::A(int num), num=" << num << ", this=" << this << "\n";
    }
};

class B {
public:
    B(int num) {
        cout << "B::B(int num), num=" << num << ", this=" << this << "\n";
    }
};

class C : public A, public B {  // 这里的继承循序 决定了初始化列表调用父类的构造函数的顺序
public:
    C() : B(200), A(100) {
        cout << "C::C(), this=" << this << "\n";
    }

    C(int num) : A(num), B(num + num) {
        cout << "C::C(int num)\n";
    }
};


int main() {
    class C boy;
    cout << "------------------------\n";
    class C girl;

    return 0;
}

在这里插入图片描述

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挥剑决浮云 -

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值