类和对象2-拷贝构造函数、赋值运算符重载

文章目录

  • 类和对象
    • 拷贝构造函数
    • 运算符重载
    • 赋值运算符重载

类和对象

拷贝构造函数

拷贝构造函数:只有一个形参,是本类类型对象的引用,通常会用const修饰,在用已经存在的类类型对象创建新对象时自动调用。

#include
using namespace std;
class Test
{
public:
	Test(int data = 0)
	{
		cout << "Create Test Obj" << endl;
		m_data = data;
	}
	Test(const Test &t)
	{
		cout << "Copy Create Test Obj" << endl;
		m_data = t.m_data;
	}
private:
	int m_data;
};
void main()
{
	Test t;
	Test t1 = t;//调用拷贝构造函数
	Test t2(t);//调用拷贝构造函数
}

上述例子中,第二个构造函数就是拷贝构造函数,我们在主函数中实例化了一个对象t,然后用这个已经存在的类类型对象去创建新对象t1和t2。我们来看一下执行效果:

类和对象2-拷贝构造函数、赋值运算符重载_第1张图片

我们再来看一个例子,更深入的理解一下拷贝构造函数。

#include
using namespace std;
class Test
{
public:
	Test(int data = 0)
	{
		cout << "Create Test Obj :" << this << endl;
		m_data = data;
	}
	Test(const Test &t)//常引用
	{
		cout << "Copy Create Test Obj :" << this << endl;
		m_data = t.m_data;
	}
private:
	int m_data;
	int m_a;
	int m_b;
	int m_c;
};
Test fun(Test x)
{
	cout << "This is fun()" << endl;
	Test Tmp(10);
	return Tmp;
}
int main()
{
	Test t(10);
	Test t1 = t;
	fun(t1);
	return 0;
}

看一下执行结果:

类和对象2-拷贝构造函数、赋值运算符重载_第2张图片

为什么会打印这么多呢?我把这个过程的指向标记了一下,如下图所示:

类和对象2-拷贝构造函数、赋值运算符重载_第3张图片

拷贝构造函数的特征:

  • 1、拷贝构造函数是构造函数的一个重载形式,是一个特殊的成员函数。
  • 2、拷贝构造函数的参数只有一个且必须使用引用形参,使用传值方式会引发无穷递归调用。
class Test
{
public:
	Test(int data = 0)
	{
		cout << "Create Test Obj :" << this << endl;
		m_data = data;
	}
	Test(const Test t)
	//此处为错误示范
	{
		m_data = t.m_data;
	}
private:
	int m_data;
};
int main()
{
	Test t1;
	Test t2 = t1;
	Test t(t1);
	return 0;
}

看一下这个怎样具体的引发了拷贝构造函数的递归调用:
类和对象2-拷贝构造函数、赋值运算符重载_第4张图片

  • 3、如果我们没有显式的定义拷贝构造函数,那么编译器会自动生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
  • 4、我们已经知道编译器生成的默认构造函数已经可以完成字节序的值拷贝了,当我们的需求只是进行简单的值拷贝的时候就可以不自己实现了,但是当需要深拷贝的时候还是需要我们自己去实现的。

运算符重载

为了增强代码的可读性,C++引入了运算符重载,运算符重载是具有特殊函数名的函数,同普通的函数一样,拥有返回值类型,函数名字以及参数列表。
函数名字:关键字operator后面加上需要重载的运算符符号。
函数原型:返回值类型 operator运算符符号(参数列表)
在进行运算符重载的时候需要注意以下几点:

  • 不能创造新的操作符
  • 重载操作符必须有一个类类型或者枚举类型的操作数
  • 用于内置类型的操作符,其含义不能改变
  • 作为类成员的重载函数时,其形参看起来会比操作数数目少1,成员函数的操作符有一个默认的形参this,限定为第一个形参

下面几个运算符不能重载

  • . (成员访问或点操作符)
  • ?: (条件操作符)
  • :: (域操作符)
  • .* (指向成员的指针操作符)
  • sizeof(取对象大小操作符)

赋值运算符重载

举个例子,把运算符重载直接作为了成员函数,以后我们可以将它作为友元函数。

#include
using namespace std;
class Test
{
public:
	Test(int data = 0)
	{
		cout << "Create Test Obj : " << this << endl;
		m_data = data;
	}
	//拷贝构造函数
	Test(const Test &t)
	{
		cout << "Copy Create Test Obj : " << this << endl;
		m_data = t.m_data;
	}
	Test& operator=(const Test &t)
	{
		cout << "Assgin : " << this << "=" << &t << endl;
		if (this != &t)
		{
			this->m_data = t.m_data;
		}
		return *this;
	}
	~Test()
	{
		cout << "Free Test Obj : " << this << endl;
	}
private:
	int m_data;
};
int main()
{
	Test t1(10);
	//调用第一个构造函数,传递值为10的形参
	Test t2;
	t2 = t1;
	//调用赋值运算符重载函数
	return 0;
}

看一下执行结果:

类和对象2-拷贝构造函数、赋值运算符重载_第5张图片

赋值运算符重载需要注意以下几点:

  • 参数类型
  • 返回值
  • 检测是否是自己给自己赋值
  • 返回*this
  • 一个类如果没有显式的定义赋值运算符重载,编译器会生成一个默认的赋值运算符重载函数,完成对象按字节序的值拷贝工作。

你可能感兴趣的:(c++,开发语言,后端)