php微网站开发,云匠网可能会遇到哪些问题,网站的底部导航栏怎么做,深圳网页设计师收入C中一般创建对象#xff0c;拷贝或赋值的方式有构造函数#xff0c;拷贝构造函数#xff0c;赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现
1.构造函数
构造函数是一种特殊的类成员函数#xff0c;是当创建一个类的对象时#xff0c;它被调用来… C中一般创建对象拷贝或赋值的方式有构造函数拷贝构造函数赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现
1.构造函数
构造函数是一种特殊的类成员函数是当创建一个类的对象时它被调用来对类的数据成员进行初始化和分配内存。构造函数的命名必须和类名完全相同
首先说一下一个C的空类编译器会加入哪些默认的成员函数
·默认构造函数和拷贝构造函数
·析构函数
·赋值函数赋值运算符
·取值函数
**即使程序没定义任何成员编译器也会插入以上的函数
注意构造函数可以被重载可以多个可以带参数
析构函数只有一个不能被重载不带参数 而默认构造函数没有参数它什么也不做。当没有重载无参构造函数时 A a就是通过默认构造函数来创建一个对象
下面代码为构造函数重载的实现
[cpp] view plain copy
span stylefont-size:14px;class A { int m_i; Public: A() { Cout”无参构造函数”endl; } A(int i):m_i(i) {} //初始化列表 }/span 2.拷贝构造函数 拷贝构造函数是C独有的它是一种特殊的构造函数用基于同一类的一个对象构造和初始化另一个对象。
当没有重载拷贝构造函数时通过默认拷贝构造函数来创建一个对象
A a;
A b(a);
A ba; 都是拷贝构造函数来创建对象b
强调这里b对象是不存在的是用a 对象来构造和初始化b的 先说下什么时候拷贝构造函数会被调用
在C中3种对象需要复制此时拷贝构造函数会被调用
1一个对象以值传递的方式传入函数体
2一个对象以值传递的方式从函数返回
3一个对象需要通过另一个对象进行初始化 什么时候编译器会生成默认的拷贝构造函数
1如果用户没有自定义拷贝构造函数并且在代码中使用到了拷贝构造函数编译器就会生成默认的拷贝构造函数。但如果用户定义了拷贝构造函数编译器就不在生成。
2如果用户定义了一个构造函数但不是拷贝构造函数而此时代码中又用到了拷贝构造函数那编译器也会生成默认的拷贝构造函数。 因为系统提供的默认拷贝构造函数工作方式是内存拷贝也就是浅拷贝。如果对象中用到了需要手动释放的对象则会出现问题这时就要手动重载拷贝构造函数实现深拷贝。
下面说说深拷贝与浅拷贝
浅拷贝如果复制的对象中引用了一个外部内容例如分配在堆上的数据那么在复制这个对象的时候让新旧两个对象指向同一个外部内容就是浅拷贝。指针虽然复制了但所指向的空间内容并没有复制而是由两个对象共用两个对象不独立删除空间存在
深拷贝如果在复制这个对象的时候为新对象制作了外部对象的独立复制就是深拷贝。 拷贝构造函数重载声明如下
A (const Aother)
下面为拷贝构造函数的实现
[cpp] view plain copy
span stylefont-size:14px;class A { int m_i A(const A other):m_i(other.m_i) { Cout”拷贝构造函数”endl; } }/span 3.赋值函数
当一个类的对象向该类的另一个对象赋值时就会用到该类的赋值函数。
当没有重载赋值函数赋值运算符时通过默认赋值函数来进行赋值操作
A a;
A b;
ba;
强调这里a,b对象是已经存在的是用a 对象来赋值给b的 赋值运算的重载声明如下 A operator (const A other) 通常大家会对拷贝构造函数和赋值函数混淆这儿仔细比较两者的区别
1拷贝构造函数是一个对象初始化一块内存区域这块内存就是新对象的内存区而赋值函数是对于一个已经被初始化的对象来进行赋值操作。
[cpp] view plain copy
span stylefont-size:14px;class A; A a; A ba; //调用拷贝构造函数b不存在 A c(a) ; //调用拷贝构造函数 /****/ class A; A a; A b; b a ; //调用赋值函数(b存在)/span 2一般来说在数据成员包含指针对象的时候需要考虑两种不同的处理需求一种是复制指针对象另一种是引用指针对象。拷贝构造函数大多数情况下是复制而赋值函数是引用对象
3实现不一样。拷贝构造函数首先是一个构造函数它调用时候是通过参数的对象初始化产生一个对象。赋值函数则是把一个新的对象赋值给一个原有的对象所以如果原来的对象中有内存分配要先把内存释放掉而且还要检察一下两个对象是不是同一个对象如果是不做任何操作直接返回。这些要点会在下面的String实现代码中体现 如果不想写拷贝构造函数和赋值函数又不允许别人使用编译器生成的缺省函数最简单的办法是将拷贝构造函数和赋值函数声明为私有函数不用编写代码。如
[cpp] view plain copy
span stylefont-size:14px;class A { private: A(const A a); //私有拷贝构造函数 A operate(const A a); //私有赋值函数 }/span
如果程序这样写就会出错
[cpp] view plain copy
span stylefont-size:14px;A a; A b(a); //调用了私有拷贝构造函数编译出错 A b; ba; //调用了私有赋值函数编译出错/span 所以如果类定义中有指针或引用变量或对象为了避免潜在错误最好重载拷贝构造函数和赋值函数。 下面以string类的实现为例完整的写了普通构造函数拷贝构造函数赋值函数的实现。String类的基本实现见我另一篇博文。
[cpp] view plain copy
span stylefont-size:14px;String::String(const char* str) //普通构造函数 { coutconstructendl; if(strNULL) //如果str 为NULL就存一个空字符串“” { m_stringnew char[1]; *m_string \0; } else { m_string new char[strlen(str)1] ; //分配空间 strcpy(m_string,str); } } String::String(const Stringother) //拷贝构造函数 { coutcopy constructendl; m_stringnew char[strlen(other.m_string)1]; //分配空间并拷贝 strcpy(m_string,other.m_string); } String String::operator(const String other) //赋值运算符 { coutoperator funtionendl ; if(thisother) //如果对象和other是用一个对象直接返回本身 { return *this; } delete []m_string; //先释放原来的内存 m_string new char[strlen(other.m_string)1]; strcpy(m_string,other.m_string); return * this; }/span 一句话记住三者对象不存在且没用别的对象来初始化就是调用了构造函数 对象不存在且用别的对象来初始化就是拷贝构造函数上面说了三种用它的情况 对象存在用别的对象来给它赋值就是赋值函数。