C++类与对象之构造函数

C++类与对象之构造函数

C++类的基本格式

首先是C++类的一个基本格式

class 基类名
{
public://成员类可以访问 ,类外也可以访问。
    
    默认构造函数命名:类名(){}   //初始化函数,可以重载,不需要返回数据类型。
    有参构造函数命名:类名(){参数}   //初始化函数,可以重载,不需要返回数据类型。
    拷贝构造函数命名:类名(基类 &类名) //将传入的人身上的所有属性,拷贝到我身上。
    
    析构函数命名:~类名(){}   //结尾进行清洗,不能重载。
    
    //属性。
    //方法(行为)。

private: //类内可以访问,类外不可以访问。

    
protected://类内可以访问,派生类可以访问,类外不能访问。
    
};

struct 和 class 区别

struct默认权限是公共

class默认权限是私有

C++类构造函数的调用方法
  • 括号法:

    • 类 命名; //默认构造函数调用,不要空括号。
    • 类 命名(参数); //有参构造函数调用。
    • 类 命名(命名对象); //拷贝函数构造调用。
    #include<iostream>
    #include<string> 
    
    using namespace std;
    
    class Person
    {
    public:
    	Person();
    	Person(string &name);
    	//Person(const Person &obj);
    	~Person();
        
    public:
    	string name="1";
    		
    }; 
    
    Person::Person(){
    	cout << "Person无参构造" << endl;
    }
    
    Person::Person(string &name){
    	this->name = name;
    	cout << "Person有参构造" << endl;
    }
    /*
    Person::Person(const Person &obj){
    	cout << "Person拷贝构造" << endl;
    }*/
    Person::~Person(){}
    
    int main(){
    	
    	Person P1;
    	
    	string name = "卡卡罗特";
    	Person P2(name); 
    	
    	Person P3(P2);  //如果采用默认的拷贝构造,则输出name时,会输出卡卡罗特
    	cout << P3.name << endl;
    	
    	return 0;
    }  
    

    当然你也可以通过Person(const Person &obj)重写拷贝构造函数

  • 显示法

    • 类 命名; //默认构造函数调用,不要空括号。
    • 类 命名 = 类(参数); //有参构造函数调用。
    • 类 命名 = 类(命名对象); //拷贝函数构造调用,不要使用拷贝构造函数,初始化匿名对象。
    Person P4 = Person(name);
    cout << P4.name << endl;
    
    Person P5 =  Person(P3);
    cout << P5.name << endl;
    

    可以把这里的类(参数)单独拿出来属于匿名对象

    使用时机:例如你用vector容器管理一个类的数组时,你可以不需要定义名字,直接使用匿名对象,然后push_back(Person())

  • 隐式转换法

    • 类 命名 = 参数; //有参构造
    • 类 命名 = 命名对象; //拷贝构造,构造之后在赋值
    Person P6 = name;  //注意这里的name必须是string,才能触发隐式转换
    Person P7 = P3;
    cout << P7.name << endl;
    

    int a = 10;

    int a;

    a = 10

    上述两者是不一样的。

构造函数调用规则
  • 如果我们什么都不写,那么编译器就会提供默认构造和拷贝构造

  • 如果我们写了有参,那么编译器就不会提供默认构造,依然提供拷贝构造

  • 如果我们写了拷贝,那么编译器就不会提供默认构造,和有参构造

可以运行我上面的案例,注释掉一部分代码,进行测试

如果我们在合作编写代码时,不希望对方使用拷贝构造,有两种方法

方法一

可以将其设置在private下面

方法二

C++11的新特性中可以设置Person(const Person &obj) = delete;

拷贝构造函数的使用时机

上面讲了那么多,无论是默认构造函数还是有参构造亦或者隐式转换赋值都有他们被使用的地方,那么对于拷贝构造函数,又常常在什么情况下使用呢,这里我具几个简单的例子来说明。

C++中拷贝构造函数的调用时机有三种:
1 使用一个已经创建完毕的对象来初始化一个新对象
2 值传递的方式给函数参数传值
3 以值方式返回局部对象

class Person
{
public:
	
		 Person()
		{
			cout << "Person默认构造函数调用" << endl;
		}

		 Person(int age)
		 {
			 cout << "Person有参构造函数调用" << endl;
			 m_Age = age;
		 }
		 Person( const Person& p)
		 {
			 cout << "Person拷贝构造函数调用" << endl;
			 m_Age = p.m_Age;
		 }
		~Person()
		{
			cout<<"Person析构函数调用" << endl;
		}
		int m_Age;
};
//1 使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
	Person p1(20);
	Person p2(p1);

	cout << "p2的年龄为:" << p2.m_Age << endl;
}
//2 值传递的方式给函数参数传值
void doWork(Person p)
{
	//因为值传递 所以会有拷贝构造函数的调用
}
void test02()
{
	Person p;
	doWork(p);
}
//3 以值方式返回局部对象
Person doWork2()
{
	Person p1;
	return p1;//值返回
}
void test03()
{
	Person p = doWork2();
}

int main()
{
//	test01();
//	test02();
	test03();
	system("pause");
	return 0;
}
拷贝构造函数的深拷贝与浅拷贝

C++编译器默认的拷贝构造函数,属于浅拷贝,你可以理解为简单的赋值语句,这样做可能会出错,如下所示

  • 如果类中存在new操作,在堆区分配空间。
  • 析构会delete掉该new操作

那么因为是简单的赋值操作,堆区空间被两个指针指向,析构时会delete两次new的空间,故产生错误。解决办法

  • 重装载赋值语句(=)
  • 重写拷贝构造函数,让赋值变成,重新分配新的空间,即深拷贝

这里只讨论构造函数的深拷贝与浅拷贝,后面会对深拷贝和浅拷贝做进一步的剖析。


如果我所写内容存在问题,欢迎讨论,如果有所帮助,希望点赞,收藏加关注,我们一起努力!!
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值