4.构造函数语义

导入:如果我们没定义任何构造函数,那么编译器就会为我们隐式自动定义一个默认的构造函数,我们称之为”合适的默认构造函数“

但是真实情况是只有在必要的时候,编译器才会合成出来,而不是必然或者必须为我们合成的。

例如

#include<iostream>
using namespace std;
​
class MATX
{
public:
};
​
class MBTX
{
public:
    int m_i;
    int m_j;
    void func()
    {
        cout << "hello";
    }
};
​
​
​
int main()
{
    MBTX myb;
​
    return 0;
}

像这个例子,如果分析了obj文件会发现编译器没有为我们合成构造函数

那么什么情况下才会合成构造函数呢?

(1)该类没有任何构造函数,但是包含了一个对象类型的成员,而该对象所属于的类有一个缺省构造函数,这个时候,编译器会为该类合成一个默认的构造函数,合成的目的是为了调用里的默认构造函数。换句话说:编译器合成了默认的构造函数,并且其中安插代码,调用的缺省构造函数

例子:

class MATX
{
public:
    MATX()
    {
        cout << "hello";
    }
};
​
class MBTX
{
public:
    int m_i;
    int m_j;
    MATX ma;
    void func()
    {
        cout << "hello";
    }
};

在obj文件中可以发现编译器自动合成了构造函数并调用了MATX的构造函数

(2)父类带缺省构造函数,子类没有任何构造函数,那因为父类这个缺省的构造函数要被调用,所以编译器会为这个子类合成出一个默认构造函数,合成的目的是为了调用这个父类的构造函数。

#include<iostream>
using namespace std;
class MATX
{
public:
    MATX()
    {
        cout << "hello";
    }
};
​
class MBTXPARENT
{
public:
    MBTXPARENT()
    {
        cout << "MBTXPARENT" << endl;
    }
};
​
class MBTX:public MBTXPARENT
{
public:
    int m_i;
    int m_j;
    //MATX ma;
    void func()
    {
        cout << "hello";
    }
};
​
int main()
{
    MBTX myb;
​
    return 0;
}

(3)如果一个类含有虚函数,但没有任何构造函数时

因为虚函数的存在,a)编译器会给我们生成一个基于该类的虚函数表,b)把类的虚函数表地址赋给类对象的虚函数表指针

#include<iostream>
using namespace std;
class MATX
{
public:
    MATX()
    {
        cout << "hello";
    }
};
​
class MBTXPARENT
{
public:
    MBTXPARENT()
    {
        cout << "MBTXPARENT" << endl;
    }
};
​
class MBTX:public MBTXPARENT
{
public:
    int m_i;
    int m_j;
    //MATX ma;
    void func()
    {
        cout << "hello";
    }
    virtual void mvirfunc()
    {
        cout << "mvirfunc" << endl;
    }
};
​
int main()
{
    MBTX myb;
​
    return 0;
}

编译器给我们往MBTX缺省构造函数中增加了代码

(1)生成了类MBTX的虚函数表

(2)调用了父类的构造函数

(3)因为虚函数的存在,把类的虚函数表地址赋给对象的虚函数表指针

#include<iostream>
using namespace std;
class MATX
{
public:
    MATX()
    {
        cout << "hello";
    }
};
​
class MBTXPARENT
{
public:
    MBTXPARENT()
    {
        cout << "MBTXPARENT" << endl;
    }
};
​
class MBTX:public MBTXPARENT
{
public:
    int m_i;
    int m_j;
    //MATX ma;
    void func()
    {
        cout << "hello";
    }
    virtual void mvirfunc()
    {
        cout << "mvirfunc" << endl;
    }
​
    MBTX()
    {
        m_i = 15;
    }
};
​
int main()
{
    MBTX myb;
​
    return 0;
}

当我们有自己的默认构造函数时,编译器会根据需要扩充我们自己写的构造函数代码,比如调用父类构造函数,给对象的虚函数指针赋值

(4)如果一个类带有一个虚基类,编译器也会为它合成一个默认构造函数。

虚基类:通过两个直接基类继承同一个简介基类,所以一般是三层,有爷爷Grand,有两个爹A,A2,有孙子C。

#include<iostream>
using namespace std;
​
​
class Grand
{
public:
};
​
class A :virtual public Grand
{
public:
};
​
class A2 :virtual public Grand
{
public:
};
​
class C : public A2, public A
{
public:
};
​
int main()
{
    C cc;
    return 0;
}

vbtable(虚基类表),vftable(虚函数表)

虚基类结构,编译器为子类和父类都产生了“合适的默认构造函数”。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值