C++ 构造函数

1、构造函数

构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值。构造函数没有返回值,可以有参数。

2、默认构造函数以及构造函数的重载

默认构造函数,如果不写的话也是可以的,编译器在执行时候发现类中没写构造函数,会自动给类中加上一个无参的构造函数,即默认构造函数。
但如果你自己编写了构造函数的重载,编译器识别到了存在构造函数,那么空参的构造函数就不会自动给你加上去, 所以建议手动写上默认构造函数。

#include<bits/stdc++.h>
using namespace std;
class A{
	//类的外部接口
    public:
        A();//默认构造函数
        A(string a,int age);//构造函数的重载
        //成员函数
        void get();
        void set(string a,int age);
     //类的成员数据 尽量隐蔽 
    private:
        int age;
        string name;
};
// 空参构造 成员数据初始化
A::A(){
    this->age=19;
    this->name="init_null";
}
//构造函数重载 传入参数 成员数据初始化
A::A(string a,int age){
    this->age=age;
    this->name=a;
}
//通过public 调用private的数据
void A::get(){
    cout<<age<<" "<<name<<endl;
}
//通过public 更改private的数据
void A::set(string a,int age){
    this->age=age;
    this->name=a;
}
int main(){
    A test;//创建一个午餐对象 会调用默认构造函数
    test.get();
    test.set("Mike",20);///通过成员函数修改成员数据
    test.get();
    A test1("test1",2);//传参用来初始化对象
    test1.get();
    return 0;
}

3、构造函数的默认值

#include<bits/stdc++.h>
using namespace std;
class A{
    public:
        A(string a="John",int age=10);//构造函数默认值
        void get();
        void set(string a,int age);
    private:
        int age;
        string name;
};
A::A(string a,int age){
    this->age=age;
    this->name=a;
}
void A::get(){
    cout<<age<<" "<<name<<endl;
}
void A::set(string a,int age){
    this->age=age;
    this->name=a;
}
int main(){
    A test;//没有传入参数就会设为默认值
    test.get();// 10 John

    A test1("Bob");//只传入了第一个参数 ,后面没有的参数为默认值
    test1.get();//10 Bob

    A test2("Mike",20);//传入了所有参数
    test2.get();//20 Mike

    return 0;
}

特别注意,如果对于构造函数给予了默认值 那么就不可以写构造函数的重载
为什么? 如下的代码段,对于A test(“666”) 是会执行第一个还是第二个呢?
两者都满足 存在了多种情况 编译器不知道选择哪个, 所以会报错。

class A{
    public:
        A(string a="John",int age=10);//构造函数默认值
        A(string b);
        void get();
    private:
        int age;
        string name;
};

4 、委托构造函数

这个很简单,就是有两个构造函数,其中委托构造函数把自己的初始化让另一个构造函数去执行罢了。

#include<bits/stdc++.h>
using namespace std;
class Clock{
	public:
	    Clock(int h,int m,int s);
	    Clock();
	    void get();
	private:
	    int hour,mintue,second;
};
//这种写法叫做 初始化列表
Clock::Clock(int h,int m,int s):hour(h),mintue(m),second(s){
}

///委托构造函数 将默认构造函数委托给了带有参数的构造函数去执行
Clock::Clock():Clock(0,0,0){
}

void Clock::get(){
    cout<<hour<<":"<<mintue<<":"<<second<<endl;
}
int main(){
    Clock myclockOne(14,22,30);
    myclockOne.get();//14:22:30
    Clock myclockTwo;
    myclockTwo.get();//0:0:0
    return 0;
}

5、复制构造函数(拷贝构造函数)

复制构造函数,就是用一个已有的对象,去初始化一个该类的对象。
复制构造函数被调用,有以下三种情况。
①用一个已有的对象,赋值给新创建的对象
其实就是把一个已有的复制一下给新创建的对象

Clock myclockOne;
Clock myclockTwo=myclockOne;

②调用函数时候,形参为该类的对象,主函数中的对象作为实参传入形参,形参把值拷贝下来后,就与实参断了联系 ,这里注意是值传递才会调用 ,引用传递不会。
因为值传递会调用复制构造函数,所以通常情况下,如果类比较复杂,建议用引用传递, 减少时间开销。

void fun1(Clock C){

}
int main(){
    Clock myclockOne;
    Clock myclockTwo=myclockOne;
    fun1(myclockTwo);
    return 0;
}

③函数返回值为类的对象时,会调用复制构造函数
这里为什么会调用呢?
表面上是将函数fun2()中的test对象返回给了主函数中的myclockOne,但是其实test是函数fun2()中的局部变量,test离开了函数fun2就消亡了。

这时候编译系统会在主函数创建一个无名的临时对象,这个临时对象的生命周期仅仅在myclockOne=fun2()这句话。调用函数fun2时,return test;这个语句,实际上是调用了复制构造函数,将test的值初始化给了临时对象,然后fun2()消亡,test对象也消亡了,但是临时对象存在于表达式myclockOne=fun2()中,计算完这个表达式后,临时对象就消失了。

Clock fun2(){
    Clock test(1,2,3);
    return test;
}
int main(){
    Clock myclockOne;
    myclockOne=fun2();
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
int cnt;
class Clock{
	public:
	    Clock(int h=0,int m=0,int s=0);
	    Clock(Clock &C);
	    void get();
	private:
	    int hour,mintue,second;
};

Clock::Clock(int h,int m,int s):hour(h),mintue(m),second(s){
}

void Clock::get(){
    cout<<hour<<":"<<mintue<<":"<<second<<endl;
}

//复制
Clock::Clock(Clock &C){
    hour=C.hour;
    mintue=C.mintue;
    second=C.second;
    cout<<"OK"<<" "<<++cnt<<endl;
}

void fun1(Clock C){
}

Clock fun2(){
    Clock test(1,2,3);
    return test;
}
int main(){
    Clock myclockOne;
    // 1、用一个对象去初始化该类的一个对象会调用 复制构造函数
    Clock myclockTwo=myclockOne;
	// 2、形参为该类的对象主函数,调用时候形参会先复制所以会调用 
	// 值传递会调用 引用传递不会
    fun1(myclockTwo)
	// 3、函数返回值是一个对象时候 会调用     至于这里为什么不输出?编译器优化了
	// 详情见  https://www.cnblogs.com/cvwyh/p/10735019.html
    myclockTwo=fun2();         
    return 0;
}

根据复制构造函数被调用的三种情况,上述代码应该会输出OK 1
OK 2
OK 3
但是并没有输出第三句话,其实这是因为编译器优化的原因,用cmd命令行运行,关掉编译器优化即可。

在这里插入图片描述
cmd运行c++的方法为 先跳转到cpp文件的文件夹
g++ 文件名.cpp -o 文件名字
然后运行 文件名.exe即可
关掉编译优化就是在编译命令最后加上 -fno-elide-constructors即可

如上图 第一次运行时没关编译器优化 第二次是关掉了编译优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我不会c语言

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

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

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

打赏作者

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

抵扣说明:

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

余额充值