【C++】类与对象(拷贝构造函数 )

[本节内容]

拷贝构造函数
区别于构造函数https://blog.csdn.net/ly_6699/article/details/87870429

类的六个默认成员函数在下面博客中讲到:
类与对象:https://blog.csdn.net/ly_6699/article/details/87870429

大家先看一段代码思考一下:

    class C {
public:
	C(int b)    //构造函数
	{
		a = b;
	}
	void Show()     //一般函数
	{
		cout << a << “     ”;
	}
private:
	int a;
};

int main()
{
	C a(100);
	a.Show();
	C a2(a);       //注意这里的对象初始化要调用拷贝构造函数
	a2.Show();
	system("pause");
	return 0;
}
运行结果:100       100 

从以上代码的运行结果可以看出,系统为对象a2自动分配了内存并完成了与对象 a 的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。

4.1概念

只有单个形参,该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型创建新对象时由编译器自动调用

4.2特征

拷贝构造函数也是特殊的成员函数,其特征如下:
1.拷贝构造函数是构造函数的一个重载形式
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)      //类类型对象的引用
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;
	Date d2(d1);        //d2是d1拷贝构造的结果
	system("pause");
	return 0;
}

在这里插入图片描述
3.若未显式定义,系统生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节节序完成拷贝,这种拷贝我们叫做浅拷贝或值拷贝。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	system("pause");
	return 0;
}

注意:默认拷贝构造函数无论是什么类型,都直接按直接进行值拷贝。
但是对string,栈…数据结构中需要开辟空间的类型无法完成拷贝,因为它们要用同一块空间完成拷贝,但无法完成同时释放。只能用深拷贝解决。

class String
{
public:
	String(const char* str = "jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~String()" << endl;
		free(_str);
	}
private:
	char* _str;
};

int main()
{
	String s1("hello");
	String s2(s1);       //  程序奔溃且输出两个~String
}

解决方法: 先开辟一个空间,再进行值拷贝

class String
{
public:
	String(const char* str = "jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~String()" << endl;
		free(_str);
	}
	String(const String& s)     //拷贝构造函数
:_str(new char[strlen(s._str)+1])     //初始化时即先开辟空间
{
	strcpy(_str, s._str);          //在进行值拷贝
} 
private:
	char* _str;
};
4.4 拷贝构造函数的几个细节
1) 拷贝构造函数里能调用private成员变量吗?

解答: 因为拷贝构造函数仍然是特殊的一个成员函数,所以操作的还是自己类的成员变量,故不受private的限制。

2) 以下函数哪个是拷贝构造函数,为什么?
1)X::X(const X&);   
2) X::X(X);    
3)X::X(X&, int a=1);  
4)  X::X(X&, int a=1, int b=2);`

解答:

    X::X(const X&);  //是拷贝构造函数    
    X::X(X);             //不是,单纯的值拷贝会引发无限递归
    X::X(X&, int=1);          //是   
    X::X(X&, int a=1, int b=2); //是

原因: 对于一个类X, 如果一个构造函数的第一个参数是下列之一,且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数。

a) X&
b) const X&
c) volatile X&
d) const volatile X&
3. 一个类中可以存在多个拷贝构造函数吗?

解答:一个类中可以存在超过一个拷贝构造函数:

class X { 
public:       
  X(const X&);      // const 的拷贝构造
  X(X&);            // 非const的拷贝构造
};

注意,如果一个类中若果只存在一个参数为 X& 的拷贝构造函数,那么就不能使用const X或volatile X的对象指向拷贝初始化了。

class X {    
public:
  X();    
  X(X&);
};    

const X cx;    
X x = cx;    // error

如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。这个默认的参数可能为 X::X(const X&)或 X::X(X&),由编译器根据上下文决定选择使用哪一个。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值