2.5、拷贝构造函数与赋值函数
2.5.1、拷贝构造函数
1、功能:用一个已知的对象来初始化一个被创建的同类对象。
2、缺省拷贝构造函数:
- 如果类中没有说明拷贝构造函数,则编译器自动生成一个具有上述形式的缺省拷贝构造函数,作为该类的公有成员,来进行对象间的位拷贝。
- 每个类都有一个拷贝构造函数
3、特点
-
函数名同类名,无返回类型。
-
只有一个参数,是对某个对象的常引用。
-
<类名>::<类名>(const <类名>&<引用名>) A::A(const A &a)
4、拷贝函数分为浅拷贝和深拷贝。
浅拷贝执行的是简单的按位拷贝,而深拷贝则是当数据成员存在有动态内存开辟时(也就是用new开辟的空间时)则应该自己写一个深拷贝构造函数,而不用系统提供的缺省拷贝构造函数,因为此时如果还是浅拷贝的话,用delete时会出现问题,所以用了深拷贝。
2.5.2、赋值函数
1、功能:用一个对象给另一个对象赋值。类似于(int i = 10; int j = 20; i = j;)这种情况。
2、特点:
- 该函数的函数名是一个操作符,必须与关键字operator合用;
- 例:<类名>&<类名>::operator =(const <类名>&<引用名>)
- 该函数只有一个参数,是对该类某个对象的常引用。
- 一般赋值操作返回对被赋值对象的引用。
1.5.3、二者区别
- 拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在了的对象调用。
- 创建一个新的对象,用其他对象对其赋值则调用拷贝构造函数。
- 用一个对象对另一个有值的对象赋值时则调用赋值函数。
//例子
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
class Person //驼峰命名法
{
public:
Person();
Person(const char *name, int age); //有参构造
Person(const Person &p); //拷贝构造函数(深拷贝)
Person &operator=(const Person &p); //赋值函数
~Person(); //析构函数(因为存在new开辟的空间内部函数体自己写的)
void setName(const char *name); //输入一个名字
void setAge(int age); //输入一个年龄
const char *getName(); //将名字传出(接口)
int getAge(); //将年龄传出(接口)
void display() const; //打印信息
private:
char *m_name;
int m_age;
};
Person::Person()
{
m_name = NULL;
m_age = 0;
}
Person::Person(const char *name, int age)
{
m_name = new char[strlen(name)+1];
strcpy(m_name, name);
m_age = age;
}
Person::Person(const Person &p)
{
cout << "Person::Person(const Person &p)" << endl;
m_name = new char[strlen(p.m_name)+1];
strcpy(m_name, p.m_name);
m_age = p.m_age;
}
Person &Person::operator=(const Person &p)
{
cout << "Person::operator=(const Person &p)" << endl;
if ( this == &p) {
return *this ;
}
if(m_name != NULL)
{
delete []m_name;
}
m_name = new char[strlen(p.m_name)+1];
strcpy(m_name, p.m_name);
m_age = p.m_age;
return *this;
}
Person::~Person() //释放掉挂载空间。
{
if(m_name != NULL)
{
delete []m_name;
}
}
void Person::display() const
{
printf("m_name: %p\n", m_name);
printf("&m_name: %p\n", &m_name);
if(m_name != NULL)
{
cout << m_name << ", " << m_age << endl;
}else
{
cout << "NO Name" << ", " << m_age << endl;
}
}
void Person::setName(const char *name)
{
if(m_name != NULL)
{
delete []m_name;
}
m_name = new char[strlen(name)+1];
strcpy(m_name, name);
}
void Person::setAge(int age)
{
m_age = age;
}
const char *Person::getName()
{
return m_name;
}
int Person::getAge()
{
return m_age;
}
int main()
{
Person p("12345", 18);
p.display();
Person p1 = p;
p1.display();
Person p2("asdfg", 20);
p2.display();
// p2 = p1 = p;
// p2.operator=(p1.operator=(p));
p2 = p;
p2.operator=(p);
p2.setName("xiaohong");
p2.display();
return 0;
}