条款5:了解C++默默编写并调用那些函数

本文详细解析了C++中构造函数与赋值操作符的工作原理,包括默认构造函数、拷贝构造函数、自定义赋值操作符等概念,并通过具体示例展示了编译器如何生成这些函数以及何时调用它们。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(一)

如下写

class Empty { };
好比如如下下(这些函数被调用,它们才被编译器创建出来。

class Empty { 
public:
	Empty() {...}
	Empty(const Empty& rhs) {...}
	~Empty() {...}            //编译器产出的析构函数是个non-virtual,除非这个class的base class自身声明有virtual析构函数。

	Empty& operator=(const Empty& rhs) {...}
};

void main()
{
	Empty e1;  //构造函数
	Empty e2(e1);//拷贝构造函数
	e2=e1;//操作符
				//析构函数
				//析构函数
}

(二)

如下:


#include <iostream>
using namespace std;

template<typename T>
class NamedObject {
public:
	NamedObject(const char* name, const T& value){nameValue=name; objectValue=value;};
	NamedObject(const string& name, const T& value){cout << "2" <<endl;};
private:
	string nameValue;
	T objectValue;
};

void main()
{
	NamedObject<int> no1("Smallest Prime Number", 2);
	NamedObject<int> no2(no1);//调用默认的copy构造函数
}

copy构造函数的调用过程:编译器生成copy构造函数,会以no1.nameValue和no1.objectValue为初值来设定no2.nameValue和no2.objectValue.

由于nameValue是string类型。所以no2.nameValue的初始化方式是调用string的copy构造函数并以no1.nameValue为实参。另一个是内置类型。no2.objectValue会以“拷贝no1.objectValue内的每一个bits"来完成初始化。


(三)赋值操作符的基本行为与上面的拷贝构造函数如出一辙,但有里那个类外:

 第一个例外:

#include <iostream>
using namespace std;

template<typename T>
class NamedObject {
public:
	NamedObject( string& name, const T& value):nameValue(name), objectValue(value){};
private:
	string& nameValue; //reference
	 const T objectValue;     //const
};

void main()
{
	string newDog("persephone");
	string oldDog("Satch");
	NamedObject<int> p(newDog,2);
	NamedObject<int> s(oldDog,36);
	//p=s;
}
拒绝赋值操作 因为reference不能指向不同的对象!

解决:如果打算在”内含reference成员“的class内支持赋值操作。必须自己定义赋值操作符。面对内含const成员,编译器也一样,更改const成员是不合法的,所以编译器也不知道如何在自己的 赋值函数内面对他们。

自己定义赋值操作符:

#include <iostream>
using namespace std;

template<typename T>
class NamedObject {
public:
	NamedObject( string& name):nameValue(name){};
	void operator=(const NamedObject& rhs)
	{
		nameValue=rhs.nameValue;
	}
private:
	string& nameValue; //reference
};

void main()
{
	string newDog("persephone");
	string oldDog("Satch");
	NamedObject<int> p(newDog);
	NamedObject<int> s(oldDog);
	p=s;
}

另一个例外是 基类将赋值操作符声明为private了。编译器将拒绝为子类生成一个赋值操作符。

请记住:

编译器可以暗自为类创造 默认构造函数,拷贝构造函数,赋值操作符,和析构函数。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值