C++——构造函数 constructor
What is constructor
- C++中,如果你想要创建一个object,有一个函数会自动被调用(不需要programmer显式调用 ),这个函数就是constructor;
- constructor的写法很独特,其function name必须和class name相同;
- constructor通过arguments上的差异进而形成ctor的overloading,当然和normal function一样,ctor也可以有default arguments;
- ctor没有返回值类型;
- ctor还有个特色功能(ctor独享),initialization list(初始化列表)。与在{ ... }内部赋值private data,initialization list速度会更快。简单讲,一个variable数值的设定有2个阶段,分别是initialization和assignment,initialization先于assignment阶段进行。initialization list就是发生在initialization阶段,{ ... }内部赋值private data属于assignment阶段。如果不使用initialization list表明你主动放弃initialization阶段工作,虽然最后你还是把数值放入到variable,但是时间晚了些,效率差了些;
默认实参,构造函数,普通函数都有这种性质。
ctor's overloading
参考:C++——overloading principle analysis
关于header file、static、inline、variable hides的一点感想
我们知道C不允许overloading,C++允许overloading。C++在编译器一侧时别到的函数名与我们看到的函数名是有很大差异的。normal function和ctor的overloading方式差不多。下图事normal function的重载。
注意:黄色部分①②两个ctor则不可以同时存在,①对于的ctor所有形参都有默认参数,这时候就相当于default ctor,和②是一样的效果。编译器在这种情况下无法做出选择。虽然这也是overloading,但是这种overloading让compiler困惑
常量成员函数
在函数后头加const,表示函数不会改变调用者的内容,或 形参在函数内部不会改变。
如果忘记加const,右下角的例子,c1是个常量,而real和imag却有可能改变c1,产生矛盾,编译器报错。
singleton——把构造函数放在private区
design patrern中 的一种模式
构造函数的作用
①构造对象:在用类定义一个对象时会自动调用构造函数
②初始化对象:类的数据成员往往放在构造函数里面初始化
③类型转换:看讲解
无论C 、C++都是强类型语言,不同类型变量之间不能随便赋值。很多时候我们认为理所当然的赋值都是借助临时变量来实现的。看代码
#include<iostream>
class Test {
public:
Test(int a=)
{
std::cout << "Create Test Object:" << this<<std::endl;
this->a = a;
}
~Test()
{
std::cout << "Free Test Object:" << this << std::endl;
}
private:
int a;
}; int main(int argc, char **argv)
{
Test t1;
t1 = ;
getchar();
return ;
}
调试结果
这里调用了2此构造函数,2次析构函数(析构顺序是栈操作顺序)。输出结果解析
第1行输出:执行第19行,调用构造函数
第2行输出:执行第20行,调用构造函数。这里创建了一个临时Test类型对象(C++为了凸显逼格把类类型的变量称为对象),100就是传入构造函数的参数。
第3行输出:第2行构造完临时对象后,赋值给了对象t1。赋值以后临时对象的生命期就结束了,这里调用析构函数,终结这个临时对象
第4行输出:第22行return 0返回后调用析构函数,终结对象t1
画图解释这一过程
这里面最关键的一个环节就是int类型到Test临时对象转换,int类型要找到一个途径来转换成Test类型。这个途径是什么呢? 构造函数
而我们代码里面恰恰有这么个构造函数,他的参数就是一个整形。如果我们干掉这个构造函数,换一个不带参数的构造函数(或者干脆不写构造函数,使用默认的),则不能将100赋值给t1
代码如下
#include<iostream>
class Test {
public:
Test()
{
std::cout << "Create Test Object:" << this << std::endl;
this->a = a;
}
~Test()
{
std::cout << "Free Test Object:" << this << std::endl;
}
private:
int a;
}; int main(int argc, char **argv)
{
Test t1;
t1 = ;
getchar();
return ;
}
#include<iostream>
class Test {
public:
~Test()
{
std::cout << "Free Test Object:" << this << std::endl;
}
private:
int a;
}; int main(int argc, char **argv)
{
Test t1;
t1 = ;
getchar();
return ;
}
这种情况直接编译不过。错误 C2679 二进制“ = ”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)。在类型转换的时候,编译器试图寻找能实现转换的构造函数,能找到就执行构造函数生成一个临时对象好用于赋值。找不到就报错。
额外补充:对于隐式类型转换,生成的临时对象具有const性质。参考 C++——引用
explicit关键字
有的时候我们会发现构造函数前面加了个关键字explicit,代码如下
#include<iostream>
class Test {
public:
explicit Test(int a = )
{
std::cout << "Create Test Object:" << this << std::endl;
this->a = a;
}
~Test()
{
std::cout << "Free Test Object:" << this << std::endl;
}
private:
int a;
}; int main(int argc, char **argv)
{
Test t1;
t1 = (Test);
getchar();
return ;
}
在进行赋值 或 类型转换的时候,如果要借助构造函数是不允许隐式转换的。所以第20行必须强制转换(显式转换)。
C++——构造函数 constructor的更多相关文章
- javascript工厂函数(factory function)vs构造函数(constructor function)
如果你从其他语言转到javascript语言的开发,你会发现有很多让你晕掉的术语,其中工厂函数(factory function)和构造函数(constructor function)就是其中的一个. ...
- 类(class)、构造函数(constructor)、原型(prototype)
类 Class 类的概念应该是面向对象语言的一个特色,但是JavaScript并不像Java,C++等高级语言那样拥有正式的类,而是多数通过构造器以及原型方式来仿造实现.在讨论构造器和原型方法前,我可 ...
- JavaScript中的类(class)、构造函数(constructor)、原型(prototype)
类 Class 类的概念应该是面向对象语言的一个特色,但是JavaScript并不像Java,C++等高级语言那样拥有正式的类,而是多数通过构造器以及原型方式来仿造实现.在讨论构造器和原型方法前,我可 ...
- 构造函数constructor 与析构函数destructor(四)
拷贝构造函数:拷贝构造函数就是在用一个类对象来创建另外一个类对象时被调用的构造函数,如果我们没有显示的提供拷贝构造函数,编译器会隐式的提供一个默认拷贝构造函数. 拷贝构造函数的定义是X(const X ...
- 构造函数constructor 与析构函数destructor(一)
构造函数定义:构造函数c++中在创建对象时自动调用,用来初始化对象的特殊函数. (1)构造函数的名字必须与类的名字相同,不能有返回值,哪怕是void 也不行. (2)通常情况下构造函数应声明为公有函数 ...
- C++ 类 构造函数 constructor
构造函数 当定义了一个整型变量: int a; 这会申请了一块内存空间来存储a,但是这块内存中原本有数据的,可能是任何值,这不是你所希望的,若你就希望a表示1,所以要把a的值赋值为1. ; 例: #i ...
- 构造函数constructor 与析构函数destructor(五)
我们知道当调用默认拷贝构造函数时,一个对象对另一个对象初始化时,这时的赋值时逐成员赋值.这就是浅拷贝,当成员变量有指针时,浅拷贝就会在析构函数那里出现问题.例如下面的例子: //test.h #ifn ...
- 构造函数constructor 与析构函数destructor(三)
(1)构造函数初始化列表: 1 class Test{ 2 int i; 3 public: 4 Test(int vi):i(vi){}//这里的从冒号开始,到右大括号结束,这一段是构造函数初始化列 ...
- 构造函数constructor 与析构函数destructor(二)
(1)转换构造函数 转换构造函数的定义:转换构造函数就是把普通的内置类型转换成类类型的构造函数,这种构造函数只有一个参数.只含有一个参数的构造函数,可以作为两种构造函数,一种是普通构造函数用于初始化对 ...
随机推荐
- LeetCode_263. Ugly Number
263. Ugly Number Easy Write a program to check whether a given number is an ugly number. Ugly number ...
- -webkit-overflow-scrolling : touch 快速滚动 回弹 效果
现在很多for Mobile的HTML5网页内都有快速滚动和回弹的效果,看上去和原生app的效率都有得一拼. 要实现这个效果很简单,只需要在元素上加一行css代码即可: -webkit-overflo ...
- 修改config中的assemblyBinding
修改config中的assemblyBinding 未测试这段代码 private void SetRuntimeBinding(string path, string value) { XmlDoc ...
- pickle.load EOFError: Ran out of input
错误原因:pickle.loads()的次数超过了pickle.dumps()的次数 https://www.cnblogs.com/cmnz/p/6986667.html
- SQL Server数据同步到Oracle
一.分别配置SQL Server和oracle数据库的连接信息并测试连接. 二.新增数据同步任务,配置规则,运行任务,查看日志. 支持数据自动定时抽取,转换,汇聚同步.支持一对多,多对一,多对多等数据 ...
- 任务调度之Quartz.Net可视化界面
上一篇关于任务调度Quartz.Net的文章中介绍了其三个核心对象IScheduler.IJob和ITrigger,我们已经知道了其基本的使用方法,可以在控制台当中运行监控.但是在实际中我们往往需要有 ...
- dotnet core JWT Demo
JWT介绍 JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.JWT的官网地址:https://jwt.io/. 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT令牌在 ...
- 关于启动kylin报Failed to find metadata store by url: kylin_metadata@hbase的问题解决
一.出问题的原因 昨天因为项目需要,要将cloudera集群改成高可用,没想到失败了,当时因为冲动手动删了几个hdfs实例的原因,导致退不到原来的状态,折腾了一天,最后终于退回了非HA的集群,但是hd ...
- [.Net] - 生成短 Guid 标识符的方法
产生字符串(例:49f949d735f5c79e) private string GenerateId() { ; foreach (byte b in Guid.NewGuid().ToByteAr ...
- Java串口通信 RXTX 解决过程
背景介绍: 由于第一次用Java与硬件通信,网上查了许多资料,在这进行整理,便于以后学习.本人串口测试是USB串口设备连接电脑,在设备管理器中找到端口名称(也可以通过一些虚拟串口工具模拟). 下面主要 ...