• c++ 构造函数介绍及一些使用的注意点


    构造函数的作用:

    1.创建对象
    2.初始化对象中的属性
    3.类型转化

    类中如果没有构造函数,则c++编译器会默认给一个缺省的构造函数,但是当我们给出构造函数时,c++编译器不会给出默认的构造函数

    特征

    1.函数名和类名相同
    2.构造函数无返回类型说明 是没有,而不是void ,即什么都不写,实际上它有返回值,返回值就是它构造的对象
    3.在程序运行时,当新的对象被建立,该对象所属的类构造函数将被自动调用,在该对象生存期中也只调用这一次。不过还可以通过定位new,对其进行二次构建
    4.可以类中定义,也可以在类外定义。
    5.不能为虚函数
    6.不可以被继承

    注意点

    1.加上explicit构造对象的问题

    1.给构造函数加上explicit之后,就不能这样初始化对象了
    在这里插入图片描述
    当我们使用{}列表初始化这样就可以了
    在这里插入图片描述

    2. 构造函数的第二个作用,类型转换的问题

    1. 当构造函数的参数列表需要一个值时的类型转换情况

    此时是可以转换的

    下面的例子是b对象分别通过显示类型转换和隐式类型转换进行赋值的情况
    在这里插入图片描述当我们给出explicit关键字之后,隐式的赋值就不可以了
    在这里插入图片描述
    第一种就相当于强制类型转换,
    而下面的实际是调用其Int的构造函数,用c的值创建一个临时对象Int,接着使用"="运算符重载把这个临时对象的值赋值给b

    我把operator=删除的话,它此时就报的错误是无法引用函数operator =
    在这里插入图片描述

    2.当构造函数中的形参需要两个值时的情况

    此时无法进行类型转换
    在这里插入图片描述
    而当形参有默认值,即构造函数的参数列表只需要一个值时,此时又可以了
    在这里插入图片描述
    由结果可以看出,此时编译器把(a,c)当成了逗号表达式,把c的值传递给了value.

    3.编译器在构造函数的时候的优化问题

    using namespace std;
    class student {
    private:
    	int age_;
    	string name_;
    public:
    
    	student(int age, string name);
    	void RegisterStudent(int age, string name);
    	void Print() {
    		cout << this->age_ << endl;
    		cout << this->name_ << endl;
    
    	}
    	student():age_(0),name_("小李") {}
    
    };
    student::student(int age, string name) {
    	
    	age_ = age;
    	name_ = name;
    }
    
    int main()
    {
    	student s = student(10, "小李");
    	student s2;
    	s2 = student(10, "小李");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    对于s和s2的创建方式是不一样的
    对于s,本来是应该先用 (10和”小李“)构造出一个将亡值对象,然后再调用student的operator= 来给s 赋值,但此时编译器进行了优化,直接使用(10,”小李“)来构造s这个对象
    当我们调试的时候就可以看出来,当构建s对象时,此时的this指针的值已经和s的地址一样了
    在这里插入图片描述

    3.创建对象的时候尽量使用{}来创建,而不是()

    using namespace std;
    class student {
    private:
    	int age_;
    	string name_;
    public:
    
    	student(int age, string name);
    	void RegisterStudent(int age, string name);
    	void Print() {
    		cout << this->age_ << endl;
    		cout << this->name_ << endl;
    
    	}
    	student():age_(0),name_("小李") {}
    
    };
    student::student(int age, string name) {
    	
    	age_ = age;
    	name_ = name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    此时我们通过界面就可以看出,s2这个对象和其它的颜色都不一样了。
    在这里插入图片描述
    此时编译器把它当成了一个函数声名,即返回值为student 函数名为 s2,形参列表为空的函数。

    4.构造函数构造对象时,构建成员对象时与初始化列表的顺序无关,和成员对象在类中的定义顺序有关

    在这里插入图片描述
    如果按照初始化列表顺序,此时value_的值应该为1,value2_的值也应该为1,
    而此时因为是按照成员变量定义的顺序,所以value_的值是一个随机值。

    构造函数为什么不能定义为虚函数?

    因为构造函数的一个作用就是设置虚表指针,如果把构造函数设置成虚函数,那么构造函数将在虚表中存着,那么在调用构造函数的时候,虚表指针还没有设置,这样就无法找到虚表,就无法调用构造函数,而要设置虚表指针,就必须得调用构造函数,此时就已经产生矛盾了,所以构造函数不能定义为虚函数。

  • 相关阅读:
    linux内核分析:探究x86
    HTML5期末大作业:美食网页主题网站设计与实现——HTML+CSS+JavaScript月饼美食食品企业网站html模板9页面
    路由器配置DMZ主机映射
    vue3导出表格excel(支持多sheet页),并自定义导出样式
    人工神经网络的基本模型,神经网络解剖学模型图
    生存资料ROC曲线的最佳截点和平滑曲线
    openstack的port重建流程【neutron port-show 中的ip信息】
    如何使用 React Native 构建信用卡扫描仪
    Socket网络编程
    基础算法之背包
  • 原文地址:https://blog.csdn.net/aoeaoao/article/details/127770693