您的位置:首页 > 编程语言 > C语言/C++

类的拷贝构造函数、赋值函数

2016-07-23 17:13 477 查看
C++中,对于一个空的类,编译器一般默认它有4个成员函数:构造函数,拷贝构造函数、赋值函数和析构函数。
构造函数的功能:在创建一个新的对象的时候给数据成员赋初值,即初始化对象。析构函数的功能:释放一个对象,在对象删除之前用它来做一些内存释放的清理工作。它们的典型应用:在构造函数中用new来为指针成员开辟一个独立的动态内存空间,而在析构函数中用delete来释放它。
在C++中对一个对象的初始化可以是下面这样:


ClassName o1("object");//A:通过构造函数设定初始值
ClassName o3(o2);//B:通过指定的对象设定初始值


由上面的代码可以知道:B中将o2作为o3的初值,o3的初始化形式要调用相应的构造函数,但是此时找不到与之匹配的构造函数,因为ClassName类中没有哪个构造函数的形参是ClassName类的对象,由此引出ClassName所隐含的一个特殊的默认构造函数,其原型是:


ClassName(const ClassName &);


这种默认构造函数就称为默认的拷贝构造函数,仅仅拷贝了内存空间的内容,这种拷贝方式被称为浅拷贝。而对于数据成员有指针类型的类来说,默认的拷贝构造函数无法完成对其内容的拷贝,此时需要自己定义一个拷贝构造函数,然后在进行数值拷贝之前,必须为指针类型的数据成员重新开辟一个独立的内存空间,这种还需要另开辟新的内存空间的拷贝方式称为深拷贝。


拷贝构造函数:其格式是带有参数的构造函数,实际上,拷贝操作的实质就是类的对象空间的引用,在C++的规定中就说拷贝构造函数的参数个数可以是1个或者多个,但是第一个参数必须是类的引用对象,参数的形式可以是类名 &对象名或者const 类名 &对象名的形式,这里的类名就是该拷贝构造函数所在的类的类名。

一旦在类中定义了拷贝构造函数,那么隐式的默认拷贝构造函数就不再有效。

测试实例:

//MyString.h
#pragma once
#include <cstddef>//定义宏NULL的头文件
//#include <Object>
#include <iostream>
#include <string.h>

using namespace std;

class String {
public:
String(const char *str = NULL);//普通构造函数
String(const String &other);//拷贝构造函数
~String(void);//析构函数
String & operator=(const String &other);//赋值函数
public:
char *m_data;
};


//MyString.cpp
#pragma warning(disable:4996)//解决strcpy编译不通过问题
#include "MyString.h"
#include <string.h>
/*
*普通构造函数
*构造函数首先根据一个字符串常量创建一个String对象
*这个构造函数首先分配了足够的内存,然后把这个字符串常量复制到这块内存
*/

String::String(const char *str) {
if (str == NULL) {
m_data = new char[1];
*m_data = '\0';
}
else {
int length = strlen(str);
m_data = new char[length + 1];
strcpy(m_data, str);
}
}

/*
*拷贝构造函数
*所有需要分配系统资源的用户定义类型都需要一个拷贝构造函数
*它可以在函数调用中以传值的方式传递一个String类型的参数
*并且在一个函数以值的形式返回String对象时实现“返回时复制”
*/

String::String(const String &other) {
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
}

/*
*定义析构函数是为了防止内存泄露,当一个String对象超出它的
*作用域时,析构函数就会释放它所占用的内存
*/

String::~String(void) {
delete[]m_data;//m_data是内部数据类型
}

/*
*赋值函数实现字符串的传值活动
*/
String & String::operator=(const String &other) {
if (this == &other)//检查自赋值
return *this;
delete[]m_data;
int length = strlen(other.m_data);//分配新的内存资源并复制其内容
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
return *this;//返回本对象的引用
}


//main.cpp
#include "MyString.h"
#include <iostream>

using namespace std;

int main() {
String MyString("My first String test!!!");
String MyString2, MyString3 = MyString;
MyString2 = MyString;
cout << "MyString:" << MyString.m_data << endl<<
"MyString2:" << MyString2.m_data <<endl<<
"MyString3:" << MyString3.m_data;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息