类的拷贝构造函数、赋值函数
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; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解