C++29题为什么选B呢?自定义view 构造函数构造函数之后,不是不会自动生成默认构造函数了嘛?

1 - C++构造函数,复制构造函数和析构函数专题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
1 - C++构造函数,复制构造函数和析构函数专题
上传于|0|0|暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢C++默认构造函数
C++ primer中的三个地方讲解了默认构造函数:
P44变量初始化规则
P227函数(构造函数)
P388类(构造函数初始化式)
P392默认构造函数
一, 变量初始化规则(P44和P227)
1,对于类类型的成员,调用该成员所属类自身的默认构造函数实现初始化。
2,内置类型成员的初值依赖于对象定义的位置,如果对象在全局作用域中定义(既不在任何函数中)或定义为静态局部对象,则这些成员将被初始化为0;
3,如果对象在局部作用域中定义,则这些成员没有初始化!
二,初始化列表
由P49和P50可知:const和引用类型的成员,不能对它们赋值,所以必须在定义时初始化!
所以,对于const对象或引用类型的对象,在开始执行构造函数的函数体之前,要完成初始化!(P389)
初始化 const 或引用类型数据成员的唯一机会是在构造函数初始化列表中!
同时,由于没有默认构造函数的类类型的成员,编译器尝试使用默认构造函数将会失败,所以也必须在初始化列表中初始化!
三, 默认构造函数的定义
在P225定义了默认构造函数:没有形参。
再看看百度百科的定义:默认构造函数(default constructor)就是在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有的形参提供默认实参的构造函数定义。如果定义某个类的变量(对象)时没有提供初始化式就会使用默认构造函数。
在P227中说:如果没有为一个类显示定义任何构造函数,编译器将自动为这个类生成默认构造函数,通常称为合成的默认构造函数,它一般用于仅包含类类型成员的类!它不会自动初始化内置类型或复合类型的成员。所以,对于含有内置类型或复合类型成员的类,通常应该定义他们自己的默认构造函数初始化这些成员。
问题:是不是所有的类都有默认构造函数?答案是否定的。
1, 虽然编译器会为类自动生成一个合成的默认构造函数,但是它仅对于包含类类型成员的类。所以对于只含有内置类型或复合类型成员的类,如果不自定义他们的构造函数,编译器不会自动为其生成一个合成的默认构造函数的!
class Sales_item{
//Sales_item():units_sold(0), revenue(0.0){}
//std:://去掉它,编译器就不会为本类自动生成默认构造函数!
unsigned units_
2, 当然,如果类显示定义了默认构造函数,但是没有为其类类型的成员在初始化列表中显示初始化,那么会调用该成员所属类自身的默认构造函数实现初始化!这部分工作也是由编译器自动添加到当前默认函数完成的!
class Sales_item{
Sales_item():units_sold(0), revenue(0.0){}//如果为isbn成员也在这里显示初始化,那么编译器将忽略string的默认构造函数~
std:://虽然显示定义的默认构造函数,但是它的初始化是由编译器自动添加完成的!
unsigned units_
3, 如果显示定义带参数的构造函数(任意的构造函数),那么编译器不会再生成默认构造函数!
(通常也会自动生成一个合成的默认构造函数,此时,类有两个构造函数!同时编译器也完成上面第2点的工作。这句话是&的,见P392)
class Sales_item{
Sales_item(double rev):units_sold(0), revenue(rev){}
unsigned units_
关于这一点需要上机测试(TODO:测试结果之后附上),因为百科上解释如下:
一个类显式地声明了任何构造函数,编译器不生成公有的默认构造函数。这这种情况下,如果程序需要一个默认构造函数,需要由类的设计者提供。
4,如果派生列的基类中有自定义的nontrivial default constructor,那么编辑器会为每一个派生类合成一个nontrivial default constructor,以调用基类自定义的nontrivial default constructor。
5,如果一个类里隐式的含有Virtual tabel(Vtbl)或者pointer member(vptr)
6,如果一个类虚继承与其他类
编译器会为每个有虚函数的类创建一个虚函数表,该虚函数表将被该类的所有对象共享。类的每个虚成员占据虚函数表中的一行。如果类中有N个虚函数,那么其虚函数表将有N*4字节的大小。 虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。 编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能&&如果有多层继承或是多重继承的情况下)。 这意味着可以通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。C++构造函数详解及显式调用构造函数
我的图书馆
C++构造函数详解及显式调用构造函数
& & & & & & & & & & & & & & & & & & & & c++类的构造函数详解&&&&&&&&&&&&&&&&&&&&&&&&
一、 构造函数是干什么的 class Counter { public: &&&&&& & // 类Counter的构造函数 &&&&&&&& // 特点:以类名作为函数名,无返回类型 & & &&&& Counter() && &&&&& { &&&&&&&&&&&&&&& m_value = 0; &&&&&&&& } private: &&&&&& && // 数据成员 & & & && int m_ } &&&&&& 该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数-&由构造函数完成成员的初始化工作 eg:&&&&Counter c1; &&&&&& 编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象c1的m_value值设置为0 故: &&&&&&& 构造函数的作用:初始化对象的数据成员。 二、 构造函数的种类 class Complex
private : &&&&&&& double&&&&m_ &&&&&&& double&&&&m_ public: &&&&&&&&//&&&&无参数构造函数 &&&&&&& // 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做 &&&&&&& // 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来 &&&&&&& Complex(void) & & & & { &&&&&&& & && m_real = 0.0; &&&&&&&&&&&& m_imag = 0.0; & & & & } &
&&&&&&& //&&&&一般构造函数(也称重载构造函数) &&&&&&& // 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理) &&&&&&& // 例如:你还可以写一个 Complex( int num)的构造函数出来 &&&&&&& // 创建对象时根据传入的参数不同调用不同的构造函数 & & & & Complex(double real, double imag) &&&&&&& { &&&& & && && m_real = &&& & && &&& m_imag =&&&&&&&&
& & & && }&
&&&&&&& //&&&&复制构造函数(也称为拷贝构造函数) &&&&&&& //&&&&复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中 &&&&&&& //&&&&若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询 有关 “浅拷贝” 、“深拷贝”的文章论述 &&&&&&& Complex(const Complex & c) &&&&&&& { &&&&&&&&&&&&&&& // 将对象c中的数据成员值复制过来 &&&&&&&&&&&&&&& m_real = c.m_ &&&&&&&&&&&&&&& m_imag&&&&= c.m_ &&&&&&& }&&&&&&&&&&&
&&&&&&& // 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象, &&&& //需要注意的一点是,这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。&&&&&& // 例如:下面将根据一个double类型的对象创建了一个Complex对象&&&&&& Complex(double r) &&&&&&& { &&&&&&&&&&&&&&& m_real = &&&&&&&&&&&&&&& m_imag = 0.0; &&&&&&& } &&&&&&&&// 等号运算符重载(也叫赋值构造函数) &&&&&&& // 注意,这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建 &&&&&&& // 若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作 &&&&&&& Complex &operator=( const Complex &rhs ) &&&&&&& { &&&&&&&&&&&&&&& // 首先检测等号右边的是否就是左边的对象本身,若是本对象本身,则直接返回 &&&&&&&&&&&&&&& if ( this == &rhs )
&&&&&&&&&&&&&&& { &&&&&&&&&&&&&&&&&&&&&&& return * &&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& // 复制等号右边的成员到左边的对象中 &&&&&&&&&&&&&&& this-&m_real = rhs.m_ &&&&&&&&&&&&&&& this-&m_imag = rhs.m_&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& // 把等号左边的对象再次传出 &&&&&&&&&&&& & // 目的是为了支持连等 eg:&&&&a=b=c 系统首先运行 b=c && && &&&&&&&& // 然后运行 a= ( b=c的返回值,这里应该是复制c值后的b对象)&&&& &&&&&&&&&&&&&&& return * &&&&&&& } };
下面使用上面定义的类对象来说明各个构造函数的用法: int main() { &&&&&&& // 调用了无参构造函数,数据成员初值被赋为0.0 & & & & Complex c1,c2;
&&&&&&&&// 调用一般构造函数,数据成员初值被赋为指定值 &&&&&&& Complex c3(1.0,2.5); &&&&&&& // 也可以使用下面的形式 &&&&&&& Complex c3 = Complex(1.0,2.5); &&&&&&&
&&&&&&& //&&&&把c3的数据成员的值赋值给c1 &&&&&&& //&&&&由于c1已经事先被创建,故此处不会调用任何构造函数 &&&&&&& //&&&&只会调用 = 号运算符重载函数 &&&&&&& c1 = c3;&&&&&&&
&&&&&&& //&&&&调用类型转换构造函数 &&&&&&& //&&&&系统首先调用类型转换构造函数,将5.2创建为一个本类的临时对象,然后调用等号运算符重载,将该临时对象赋值给c1 &&&&&&& c2 = 5.2;&&&&&&&
& & && // 调用拷贝构造函数( 有下面两种调用方式)
&&&&&&& Complex c5(c2); & & & & Complex c4 = c2;&&// 注意和 = 运算符重载区分,这里等号左边的对象不是事先已经创建,故需要调用拷贝构造函数,参数为c2 //这一点特别重要,这儿是初始化,不是赋值。其实这儿就涉及了C++中的两种初始化的方式:复制初始化和赋值初始化。其中c5采用的是复制初始化,而c4采用的是赋值初始化,这两种方式都是要调用拷贝构造函数的。}
三、思考与测验 1. 仔细观察复制构造函数 &&&&&&& Complex(const Complex & c) &&&&&&& { &&&&&&&&&&&&&&& // 将对象c中的数据成员值复制过来 &&&&&&&&&&&&&&& m_real = c.m_ &&&&&&&&&&&&&&& m_img = c.m_ &&&&&&& }&&&&&&&
为什么函数中可以直接访问对象c的私有成员? 答:(网上)因为拷贝构造函数是放在本身这个类里的,而类中的函数可以访问这个类的对象的所有成员,当然包括私有成员了。 2. 挑战题,了解引用与传值的区别 & Complex test1(const Complex& c) & { & & & & & & } && Complex test2(const Complex c) & { & & & && && } &&& Complex test3() && { &&&&&&&&& static Complex c(1.0,5.0); & &&&&&&& && } && Complex& test4() & { &&&&&&&& static Complex c(1.0,5.0); &&&&&&&& & }&
& void main() & { & && && Complex a,b;&&&
& && && // 下面函数执行过程中各会调用几次构造函数,调用的是什么构造函数?&&&
& & && test1(a); & & && test2(a);&&&&
& & && b = test3(); & & && b = test4();&&&&
& & && test2(1.2); & & && // 下面这条语句会出错吗? & & && test1(1.2);&&&& //test1( Complex(1.2 )) 呢? & }& 答:为了便于看构造函数的调用效果,我将类重新改一下,添加一些输出信息,代码如下:View Code
& 下面是程序运行结果:第一次运行结果 第2次运行结果第3次运行结果&四、附录(浅拷贝与深拷贝)&&&&&& 上面提到,如果没有自定义复制构造函数,则系统会创建默认的复制构造函数,但系统创建的默认复制构造函数只会执行“浅拷贝”,即将被拷贝对象的数据成员的 值一一赋值给新创建的对象,若该类的数据成员中有指针成员,则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同,delete该指针 时则会导致两次重复delete而出错。下面是示例:& 【浅拷贝与深拷贝】& #include &iostream.h& #include &string.h& class Person
{ public : &&&&&&&& // 构造函数 &&&&&&& Person(char * pN) &&&&&&& { & & & & && && cout && "一般构造函数被调用 !\n"; & & & & && && m_pName = new char[strlen(pN) + 1]; & & & & & & & //在堆中开辟一个内存块存放pN所指的字符串 & & & & & & & if(m_pName != NULL)
&&&&&&&&&&&&& { &&&&&&&&&&&&&&&& //如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它 & & & & & & & &&&& strcpy(m_pName ,pN); &&&&&&&&&&&&& } &&&&&&& }&&&&&&&& &&&&&&&
&&&&&&& // 系统创建的默认复制构造函数,只做位模式拷贝 &&&&&&& Person(Person & p)&&&& &&&&&&& {
& & & & & & && && //使两个字符串指针指向同一地址位置&&&&&&&&
&&&&&&&&&&&&&&&& m_pName = p.m_pN&&&&&&&&
& & & & } &&&&&&&& ~Person( ) &&&&&&& { & & & & & && && delete m_pN &&&&&&& } & private :
&&&&&&&&char * m_pN };
void main( ) {
&&&&&&& Person man("lujun"); &&&&&&& Person woman(man);
&&&&&&& // 结果导致&& man 和&&&&woman 的指针都指向了同一个地址 &&&&&&&
&&&&&&& // 函数结束析构时 &&&&&&& // 同一个地址被delete两次 } // 下面自己设计复制构造函数,实现“深拷贝”,即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员 Person(Person & chs); { & & & && // 用运算符new为新对象的指针数据成员分配空间 && & & & m_pName=new char[strlen(p.m_pName)+ 1];
&&& & && if(m_pName)&&&&&&&&
& && &&& { & & && &&&&& & & // 复制内容 & & & &&&&& & & strcpy(m_pName ,chs.m_pName); & && &&& } &&&&&
& & &&& // 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了 }
TA的最新馆藏
喜欢该文的人也喜欢关于C++默认构造函数的有关问题 - VC/MFC当前位置:& &&&关于C++默认构造函数的有关问题关于C++默认构造函数的有关问题&&网友分享于:&&浏览:4次关于C++默认构造函数的问题参照一段java代码class A{ & & public A(int i); & public void dosmt();}class B{ & A & void fun(){ &
a.dosmt(); & }}如果是C++代码那么在类B中声明A a会报错,因为A没有无参构造函数请问如何解决这个问题------解决方案--------------------你可以先给A初始化一个值,然后给B定义一个函数去重新设置A的值。B::B(int i):a(0)//这里你随便给个值也可以,反正跟你要的效果是一样的{}如果A没有定义构造函数,i的值是一个随即值。
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有

我要回帖

更多关于 swift 自定义构造函数 的文章

 

随机推荐