-
2021-02-27 17:32:31
- 缺省构造函数(指没有参数的构造函数)
- 构造函数能初始化对象,而缺省构造函数则可以不利用任何在建立对象时的外部数据就能初始化对象
关于缺省构造函数的问题
#include<iostream> #include<string> using namespace std; class Person { public: string name; Person(string str){ name = str; //初始化姓名 } ~Person(); }; int main() { // Person student[2]; /* 报错,因为数组student[2]会调用无参构造函数,若类里面没有无参构造函数 则会报错 */ // 解决办法: //正确 // Person student[]={ // Person("xiaoming"), // Person("xiaohong"), // }; // 或一个通用解决方案,定义一个指针数组替代 typedef Person* STU; STU student[2]; //没有调用构造函数 STU *student = new STU[2]; //没有调用构造函数 /* 注意使用new分配的内存要用delete进行删除,如果使用了普通的数组删除方法, 那么你程序的运行将是不可预测的。这是因为:直接删除一个不是用 new 操作符来分配的内存指针,其结果没有被定义。 */ return 0; }
关于缺省构造函数使用问题
- 有缺省构造函数
- 方便初始化对象(如vector a),但是提供无意义的缺省构造函数也会影响类的工作效率(如果成员函数必须测试所有的部分是否都被正确地初始化,那么这些函数的调用者就得为此付出更多的时间)
- 没有缺省构造函数
- 确保每一个对象的初始化有意义,比如学生对象要带上姓名等
更多相关内容 -
C++ 构造函数的重载、缺省构造函数、类型转换构造函数、拷贝构造函数
2021-01-27 18:57:282. 缺省构造函数 只要对象被创建,就会调用构造函数 #include <iostream> using namespace std; class A { public: A(void){ cout << "无参构造函数" << endl; m_i = 0; } private: int...1. 缺省构造函数
- 只要对象被创建,就会调用构造函数。 如果类中没有定义构造函数,编译器会自动给一个无参缺省构造函数。
- 构造时,一定先构造成员子对象
1.1 代码示例
#include <iostream> using namespace std; // 这里A类中已经构造函数,那么编译器不会再提供缺省构造函数 class A { public: A(void){ cout << "无参构造函数" << endl; m_i = 0; } int m_i; }; // B类中没有构造函数,编译器在编译B类时,会自动添加一个缺省的无参构造函数 class B { public: // 构造函数对基本类型的成员变量, 不做初始化 int m_j; // 对类类型成员变量(成员子对象),将自动调用相应类的缺省构造函数来初始化 A m_a; }; int main(void){ // 用B类以无参的方式实例化一个对象,创建对象就一定会用到构造函数 // 但B类中没有构造函数, 编译器会自动给一个缺省的无参构造函数 B b; cout << b.m_j << endl; //没有做初始化,结果未知 cout << b.m_a.m_i << endl; //0 return 0; }
$ ./a.out 无参构造函数 # A类的构造函数 -718891504 # 没有做初始化,结果未知 0
2. 类型转换构造函数
- 一般构造函数参数只有一个的话,它都可以实现将参数类型转换为当前类类型的对象。
2.1 代码示例
#include <iostream> using namespace std; class Integer { public: Integer(void){ cout << "Integer(void)" << endl; m_i = 0; } // 类型转换构造函数 // 本例子中,实现把一个整型数据转换成Integer类类型 /*explicit*/ Integer(int i){ cout << "Integer(int)" << endl; m_i = i; } void print(void){ cout << m_i << endl; } private: int m_i; }; int main(void){ Integer i; i.print(); // 0 // 1. 隐式转换 // i是类类型的对象,而100是一个基本类型变量。但是100必须要转成Integer类类型才能对i进行初始化 // 编译器会从Integer找到有参构造函数,将100当做实参,构造出一个Integer类型的临时对象,所以又会调用一次构造函数 // 再用这个临时对象对i进行初始化, 隐式: 编译器会把 i = 100; => i = Integer(100); i = 100; i.print(); // 100 // 2. 显示转换, 跟上面做的事是一样的 // 如果 Integer(int i) 前加了explicit,那么必须显示 // 从语感角度来理解: 用Integer实例化一个匿名对象,再用匿名对象对i初始化 i = Integer (200); i.print(); // 200 return 0; }
Integer(void) # Integer i; 0 Integer(int) # i = 100; 100 Integer(int) # i = Integer(200); 200
3. 拷贝构造函数
- const, 可以防止意外地修改源对象。也可以接收常类型的对象
- &,可以提高传参效率,并且如果不加,会发生实参到形参的拷贝操作,这样就又会调用拷贝构造函数,发生死递归的情况, 当然编译器也不允许不加&。
3.1 代码示例
#include <iostream> using namespace std; class A{ public: A(int data = 0) { cout << "A(int)" << endl; m_data = data; } // 拷贝构造函数 // 如果这里没有&,就会有实参到形参的拷贝(也就是对象到对象的拷贝, 又会调用拷贝构造函数, 发生死递归) A(const A& that) { cout << "A(const A&)" << endl; m_data = that.m_data; } int m_data; }; int main(void){ A a1(100); // 拷贝构造, 用已经存在的对象a1作为构造实参实例化对象a2 // 1. 写法1 A a2(a1); // 2. 写法2 // 要像上面那样理解,不能把=当做赋值操作 A a3 = a1; cout << a1.m_data << endl; cout << a2.m_data << endl; cout << a3.m_data << endl; return 0; }
$ ./a.out A(int) A(const A&) A(const A&) 100 100 100
4. 缺省拷贝构造函数
4.1 代码示例
#include <iostream> using namespace std; class A{ public: // 缺省构造函数 A(int data = 0) { cout << "A(int)" << endl; m_data = data; } // 拷贝构造函数 // 如果这里没有&,就会有实参到形参的拷贝(也就是对象到对象的拷贝, 又会调用拷贝构造函数, 发生死递归) A(const A& that) { cout << "A(const A&)" << endl; m_data = that.m_data; } int m_data; }; // B中没有定义构造函数,和拷贝构造函数,编译器会给分配缺省的 class B{ public: A m_a; //成员子对象 }; int main(void){ // 调用B的缺省构造函数实例化一个对象b1 // 对于成员子对象m_a, 将会调用A中的缺省构造函数 B b1; cout << b1.m_a.m_data << endl; // 0 // 调用B的缺省拷贝构造函数实例化一个对象b2 // 对于成员子对象m_2, 将会调用A中的相应类型的拷贝构造函数,完成拷贝初始化 B b2(b1); cout << b2.m_a.m_data << endl; // 0 return 0; }
$ ./a.out A(int) 0 A(const A&) 0
总结
- c++类中有一个对象自恰性设计思想,对于B类中所包含的成员子对象,子对象的所有操作都应该由类型的提供者(B?)来完成。
- 以无参的方式创建了b1,那么子对象m_a也会以无参方式创建。以拷贝的方式创建了b2,那么子对象m_a也会以拷贝方式创建。
5. 拷贝构造函数的调用时机
5.1 代码示例
#include <iostream> using namespace std; class A{ public: A(void){ cout << "A的无参构造" << endl; } A(const A& that){ cout << "A的拷贝构造函数" << endl; } }; // 参数是A类型对象的函数 void func(A a){} // 返回值是A类型对象的函数 A bar(void){ A a; cout << &a << endl; // 把函数返回结果a 拷贝给 临时对象保存,会用到拷贝构造函数 return a; } int main(void){ A a1; // 无参构造 1次 A a2 = a1; // 拷贝构造 1次 func(a1); // 拷贝构造(传参) 1次 A a3 = bar(); // 无参构造(bar 中),拷贝构造(bar 中,a到临时对象),拷贝构造(临时对象到a3) 3次 cout << &a3 << endl; return 0; }
$ ./a.out A的无参构造 A的拷贝构造函数 A的拷贝构造函数 A的无参构造 # 编译器会让a3直接引用a, a3就是a的别名。这样就少使用了两次拷贝构造函数。#NRV,参考《深度探索C++对象模型》 0x7ffce5d15ac7 0x7ffce5d15ac7
去优化就正常了
$ g++ a.cpp -fno-elide-constructors $ ./a.out A的无参构造 A的拷贝构造函数 A的拷贝构造函数 A的无参构造 0x7ffdd3cd9237 A的拷贝构造函数 A的拷贝构造函数 0x7ffdd3cd9256
-
关于C++缺省构造函数的讲解——精解
2019-03-15 12:36:00构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行, 构造函数的名称与类的名称是完全相同的,...若程序员没有主动给类定义构造函数,编译器自动给一个缺省的构造函数。 一旦程序员定...1.构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行,
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
在这里有几点要注意的问题:1. 构造函数在实例化对象时自动被调用,且在每个对象的生命期仅被调用一次。
2. 可以被重载。
3. 若程序员没有主动给类定义构造函数,编译器自动给一个缺省的构造函数。
4. 一旦程序员定义了一个构造函数,系统将不会再给出缺省构造函数。
5. 除了系统缺省的构造函数外,只要构造函数无参或者参数有缺省值, 编译器会认为它就是缺省构造函数。缺省的构造函数同时只能有1个。2.缺省构造函数
那么何为缺省构造函数呢?即无参或参数有缺省值。仅仅是为了构造对象。
让我们来看一段代码:#include<iostream> using namespace std; class Test { public: Test()//缺省构造函数 { } Test(int a=8,int b=10)//缺省构造函数 { } private: int data; }; int main() { return 0; }
这段代码中的两个构造函数即为两种缺省构造函数的形式。一种是构造函数不含形参,另一种是构造函数含有形参,并且形参被赋有默认值
3.构造函数重载
构造函数重载即函数名相同,参数个数或者参数类型不同,根据参数进行区分。
例如:#include <iostream> using namespace std; class Test { public: Test()//缺省构造函数 { data=0; cout<<"缺省构造函数,初始化数据"<<this<<endl; } Test(int d)//不是缺省构造函数 { data=d; cout<<"带1个参数构造函数,初始化数据"<<this<<endl; } Test(int x,int y)//不是缺省构造函数 { this->x=x; this->y=y; cout<<"带2个参数构造函数,初始化数据"<<this<<endl; } Test(int data,int x,int y)//不是缺省构造函数 { this->data=data; this->x=x; this->y=y; cout<<"带3个参数构造函数,初始化数据"<<this<<endl; } private: int data; int x; int y; }; int main() { Test t; //实例化对象,调用无参的构造函数时不能加括号,否则系统认为在声明一个函数t() Test t1(10); Test t2(20,30); Test t3(11,22,33); return 0; }
程序运行结果:
我们可以很明显的看出4个构造函数的形参个数不同,但在创建对象时程序会自动的匹配相对应的构造函数来实例化对象。让我们再看一段代码:
#include<iostream> using namespace std; class Test { public: Test()//缺省构造函数 { data=0; cout<<"缺省构造函数,初始化数据"<<this<<endl; } Test(int x)//不是缺省构造函数 { this->x=x; cout<<"带一个参数的构造函数,初始化数据"<<this<<endl; } Test(float y)//不是缺省构造函数 { this->y=y; cout<<"带一个参数的构造函数,初始化数据"<<this<<endl; } private: int data; int x; float y; }; int main() { Test t; Test t1(10); Test t2(9.8f); return 0; }
程序运行结果:
我们可以看出上述这段代码的构造函数的形参类型不同,但在创建对象时程序会自动的匹配相对应的构造函数来实例化对象。4.带默认形参值的构造函数(等价于缺省构造函数中的参数有缺省值类型)
我们通常编写的程序中形参是不会被赋值的,但其实它也可以被赋予默认值,而这种形式的函数被叫做带有默认形参值的函数,而构造函数同样也适用于这个规则。
让我们来看一段代码:#include <iostream> using namespace std; class Test { public: Test(int x=0,int y=0)//缺省构造函数 { this->x=x; this->y=y; cout<<"带2个参数构造函数,初始化数据"<<this<<endl; } private: int data; int x; int y; }; int main() { Test t; //定义对象时不能加括号,否则系统认为在声明一个函数t() Test t1(10); Test t2(20,30); return 0; }
程序运行结果:
对于有参数的构造函数,若为非缺省构造函数,则实参的个数必须与形参的个数一致,若为缺省构造函数(参数有缺省值类型) ,则实参的个数可以少于形参的个数(即上述形式),写入的实参值会取代掉形参的默认值,而未写入实参值的内存空间将会使用形参的默认值。希望我的解答可以帮助到你。
-
c++缺省构造函数
2020-03-14 21:29:20c++缺省构造函数类内嵌对象 类 书写实验报告时发现一个问题,首先写了一个类 如果说写这个程序的人是为了不让编译器产生缺省构造函数,那么他显然达到了这个目的。 但实际上在public中已经有构造函数的情况下,...类
书写实验报告时发现一个问题,首先写了一个类
如果说写这个程序的人是为了不让编译器产生缺省构造函数,那么他显然达到了这个目的。
但实际上在public中已经有构造函数的情况下,编译器是不会产生缺省构造函数的,因此如果去掉private里面的Date(){}该程序依旧会报错。
那如果把自己写的构造函数全部放在private里面呢,让public里面没有构造函数,编译器会产生缺省构造函数吗?
很可惜,我们实验的结果告诉我们只要在class里面定义了构造函数,编译器就不会产生默认的构造函数。内嵌对象
内嵌对象用的不多,网上也很少有这方面的介绍,恰好我写的这个实验用到了内嵌对象,我继续使用上面介绍的Data类,但是在public里面声明构造函数且不允许参数缺省,类似于本文章第一张图片,然后定义另一个类people在里面内嵌对象,该对象的类就是Data,如果我们要实现这个people类的缺省构造函数应该怎么办呢?
我首先尝试了不写构造函数,让编译器产生缺省构造函数,但是失败了,失败的原因其实很容易想到,因为要缺省构造people,那么就一定会缺省构造里面的Data,但可惜的是Data类并不存在缺省构造函数,因此people类也不可能存在缺省自构函数。
下面把Data类的缺省构造函数写入public,再次进行上述相同的实验。
成功编译,在此我们摸清了嵌入对象类的缺省构造函数用法,它必须保证自己所有的元素能够缺省自构,那么它才可以缺省自构,并且必须存在缺省自构函数在public里面。 -
缺省构造函数
2016-03-03 21:54:07第4章:初始化与清除 本篇博客主讲 缺省构造函数 -
构造函数与缺省构造函数
2018-07-26 14:54:59比如我们构造一个类A和一个继承A的结构体B class A { public: int a; }; struct B:A { }; 他们之间可以是相互的继承关系,因此执行以下操作是被允许的 B b; b.a = 0; cout << b.a <&... -
C++中构造函数的参数缺省的详解
2020-12-31 13:40:19C++中构造函数的参数缺省的详解 前言: 构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。在构造函数中也可以采用这样的方法来实现初始化。 #... -
C++基础:缺省构造函数
2014-05-10 16:01:50缺省构造函数是C++以及其他的一些面向对象的程序设计语言中, -
缺省构造函数不能处理隐式超构造函数抛出的异常类型 IOException。必须定义显式构造函数
2016-02-01 02:22:03int lastnum = getNum(source.getProperty("fileName")); public static int getNum(String Filename) throws ... 第一行报错:缺省构造函数不能处理隐式超构造函数抛出的异常类型 IOException。必须定义显式构造函数 -
C++ 类缺省构造函数调用带参数的构造函数
2015-03-29 10:52:52通过以上分析,我感觉对于笔试题而言,在缺省构造函数内部调用带参构造函数时,不是将带参构造函数当做普通函数执行函数调用,而是再一次实例化对象,在内存中重新开辟空间,并执行了带参构造函数后的初始化列表;... -
构造函数缺省参数
2021-04-13 11:24:22[解析] 构造函数是类的一个特殊成员函数,它与类同名,并且没有返回值。C++在创建一个对象时,会自动调用类的构造函数,在构造函数中可以执行初始化成员变量的操作。...[解析] C++在创建一个对象时,会自动调用类的构造... -
为什么 没有缺省构造函数的类类型成员 必需要在初始化列表 里初始化 ?
2016-06-06 15:22:59名词解释 1、缺省构造函数:类的构造函数无参或参数默认值统称为缺省构造函数。 2、初始化列表:与其它函数不同,构造函数除了有名字,参数列表和函数体外还可以有初始化列表。列表以冒号开始后跟以逗号隔开的初始... -
ITEM4避免无用的缺省构造函数
2020-11-04 11:20:53避免无用的缺省构造函数 有些对象不利用外部数据就进行初始化时不合理的;入公司或个人的ID; 提供无用的缺省构造,增加其他成员函数对成员变量合法性的判断及错误处理;是的类的处理效率降低; 没有缺省构造函数... -
C++默认构造函数的问题
2020-12-22 16:14:23C++ defaul construct :缺省构造函数(默认构造函数) 定义:第一种 构造函数没有参数,即是 A()形式的 第二种 构造函数的全部参数由缺省值提供,A(int a=0,int b=0) 编译器添加的默认构造函数的条件... -
C++ Primer中关于缺省构造函数的叙述
2011-10-19 16:21:26只有当没有构造函数或声明了缺省构造函数时,我们才能不指定实参数集来定义类对象。...尤其是,如果一个类声明了一个包含多个参数的构造函数,但没有声明缺省构造函数,则每个类对象的定义都必须提供所需的实参。 ... -
关于缺省构造函数
2010-03-22 21:56:00今天拿着《Effective C++》和《More Effective C++》结合着看了一下,主要看了有关构造函数和析构函数的几条item,其中对缺省构造函数的感受颇深。 构造函数能初始化对象,而缺省构造函数不需利用附加的外部数据就... -
C++之缺省参数的构造函数、缺省的构造函数及缺省的析构函数
2013-10-31 13:53:05缺省参数的构造函数 一、对于带参数的构造函数,在定义对象时必须给构造函数传递参数,否则构造函数将不被执行。 但是在实际应用中,有些构造函数的参数值通常是不变的,只有在特殊情况下才需要改变它的参数值,... -
More Effective C++----(4)避免无用的缺省构造函数 & (5)谨慎定义类型转换函数
2016-05-04 16:57:36Item M4:避免无用的缺省构造函数 缺省构造函数(指没有参数的构造函数)在C++语言中是一种让你无中生有的方法。构造函数能初始化对象,而缺省构造函数则可以不利用任何在建立对象时的外部数据就能初始化对象。有时... -
C/C++编程:避免无用的缺省构造函数
2018-08-31 09:18:00构造函数能够初始化对象,而缺省构造函数能够不利用任何在建立对象时的外部数据就能初始化对象,这很方便,但是有时候是不合理的。 举个例子,有一个类,它表示公司的设备,这个类包含一个ID代码,这个ID代码被强制... -
慎用缺省构造函数的一种场景
2014-08-07 20:25:22本文通过示例来谈谈慎用缺省构造函数的一种设计场景。 -
Java错误:默认构造函数未定义隐式超级构造函数
2021-02-12 23:12:23} } 如果不向类添加构造函数(any),编译器会为你添加缺省的无参数构造函数。 当defualt没有arg调用super();因为你没有超级类,你会得到错误信息。 这是关于它自己的问题。 现在,扩大答案: 你是否意识到创建一个... -
构造缺省函数
2016-11-14 23:51:17内容(A):每个类都有构造函数,如果没有定义,则系统自动生成一个缺省的构造函数。该缺省的构造函数没有参数,其函数体内也没有语句,它仅用来生成对象而不是初始对象。只要用户在定义类时定义了构造函数,编译... -
C++类中的4个特殊函数 - 缺省构造函数、拷贝构造函数、拷贝赋值操作符和析构函数
2011-03-02 21:36:00http://sue602.blog.163.com/blog/static/314953072010621326354/ -
构造函数参数的缺省
2019-03-08 16:23:52//构造函数参数的缺省 using namespace std; //以一个点的横竖坐标,以及坐标改变作为例子来说明。 class point { private: int x; int y; public: point(int,int); ~point(); void change(int,int); ... -
C++构造函数初始化顺序详解
2021-01-01 01:27:172.缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空 3.创建一个对象时,系统自动调用构造函数 析构函数 1.析构函数没有参数,也没有返回值。不能重载,也... -
必须定义显式构造函数Error Java
2021-03-01 08:34:25获得“默认构造函数不能处理由隐式超级构造函数抛出的异常类型IOException。必须定义一个显式构造函数”私人FileWriter fileWriter =新的FileWriter(文件);具体来说,我的问题是.....我如何创建filewriter的显式构造...