我的编程空间,编程开发者的网络收藏夹
学习永远不晚

c++11 类中关于default、explict、implicit、noexcept、final的详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

c++11 类中关于default、explict、implicit、noexcept、final的详解

default

default是c++11的标准,它的作用是告诉编译器声明一个无参的默认构造函数。

最初的时候我们声明类是这样的:


class test{
    
    public:
        int add(){}
};

由于我们没有给默认构造函数,c++编译器隐式的帮我们增加了一个默认的无参构造函数,注意这一点取决于编译,有的编译器不会增加,但大多数都会,如GCC、MSVC。

但是一旦我们声明了一个有参的构造函数:


class test{
    
    public:
        test(int a){}
        int add(){}
};

那么编译器就不会为我们提供默认的无参构造函数了,就会在声明变量时必须传入参数了。

所以诞生了default关键字,只需要在无参的构造函数后面加上它就可以了


class test{
    
    public:
        test() = default;
        test(int a){}
        int add(){}
};

那么问题来了,它和我们手动声明无参构造函数有什么区别?

区别一:当使用多文件编程时,使用default声明的构造函数不需要在写实现

区别二:代码执行效率,当我们使用这个关键字定义的构造函数,在声明变量时,编译器不会去调用构造函数,也不会生成构造函数的代码,这点是重点,高效率提高声明变量的时间,如果用户自己声明了构造函数会造成编译器开辟完内存后会去调用一次构造函数。

explict

这个关键字的作用是用于修饰只有一个参数的构造函数,并要求为显示的

那么显示的是什么意思呢?为什么只能修饰一个构造函数呢?

首先我们来看这段代码


class test{
    
    public:
        test(int a){}
};
 
int main(){
 
    test a(0);
    test b = 2;
}

大家可以看到上面用了两种方式的初始化,一种是(),还有一种是=号,注意这里讲一下区别在哪,()构造会直接调用最匹配的构造函数,并且不会发送隐式转换,如果用=号则编译器需要推导,推导=号右边是一个什么类型,然后去选择与这个类型匹配的构造函数

但是也可能产生一种问题:


class test{
    
    public:
        test(int a){}
        test(char a){}
};
 
int main(){
 
    test a(0);
    test b = 2;
}

这里增加了一个参数char的构造函数,那么这个时候可能产生一种问题,就是char是可以用来表示整数的,而2又符合char能表示的范围,所以这里就可能产生了隐式转换,将2转换为了char类型,我们用户甚至可以手动强转,如果编译器够聪明的话会选择正确的构造函数,如果不够聪明呢?

所以为了解决可能产生的这种问题就推出了:explict关键字,用这个关键字声明的构造函数是不允许用户去做可能产生隐式转换的事情


class test{
    
    public:
        explict test(int a){}
        test(char a){}
};
 
int main(){
 
    test a(0);
    test b = 2;    //这一行会报错,因为可能会发生隐式转换
    //test b = '2' //这样也不行的,因为会优先匹配具有explict的构造函数,那么这样就产生了隐式转换,因为'2'可以被转换成ascii码
}

因为有了explict关键字的存在任何可能发生隐式转换的动作都会被编译器报错,但是如果你用()来调用就没事的

test b('c') ;

因为()会明确表示入参类型,=号的话编译器是需要推导=号左右两边类型,在去调用最合适的构造函数,那么这个时候就产生了可能发生隐式转换的问题。

同时=号初始化也会拖累编译速度,最后明确一点,就是顺序,当调用时编译器会优先匹配explict的构造函数,就如刚刚的test b = '2',已经明确是char符号了,但是编译器仍然认为它可能会出现隐式转换,因为使用explict关键字后你做的任何可能产生类型转换的操作都会被编译器优先裁决。

最后在说明一点就是为什么只能用于只有一个参数的构造函数,为什么不能是多个?

答:因为多个的情况下是无法明确类型的,如果参数有两个或两个以上的情况下,编译器这样是不好推断的,因为两个变量可能是不同的类型,如果是两个不同的类型,那就不能做类型限定,其次类型较多的情况下对于编译器来说也是一种负担。

explict的意义就是在于针对一个变量的构造函数时方式那一个参数类型出现隐式转换,这个是与开发者们有关,最初开发者们写了多个只有一个参数的构造函数时,有时会发生隐式转换导致调不到理想的构造函数,但是多个参数的构造函数因为类型会更明确一点,所以不会出现这样的问题。

implicit

这个关键字其实根explict是相反的,它其实不存在于c++,只在java和c#这样继承c++特性的语言里存在,它表明的是隐藏的,就是表明构造函数可以被隐式转换,只是后来人们把没有使用explict声明的只有一个参数的构造函数都认为隐式带了一个implicit,不知道是谁提的,就挺离谱的,java和c#明明是继承c++,但是后来人们全把这个类型隐式加到c++中。

noexcept

这是c++11增加的函数,目的是为了提升函数效率,即告诉编译器这个函数不会产生异常。

首先开发者们在给函数加上这个关键字时应明确,你的这个函数不会出现任何问题


class test{
    
    public:
        explict test(int a)noexcept {}
       
};

这里异常的意思是指:段错误和任何可能引起程序崩溃的代码。

c++里有一套机制,就是c++好像对系统层的某些异常做了捕获,当我们使用std::string,在初始化时传入一个NULL时会导致段错误,然后系统会杀死程序,但我发现在杀死之前会先去调用c++的std::terminate(),然后这个函数内部调用std::abort()来杀死我们的程序,在Linux中有消息事件可以完成这个操作。

所以我认为这个关键字的作用就是告诉编译器不要对这个函数做监听,这样就可以提升函数的执行效率,否则当调用这个函数时c++还要去做一些事件监听的注册功能,因为如果一开始全都监听的话c++也不知道你什么时候才会调用,所以最合适的是调用的时候监听。

那么这样的话就提升了函数调用时的一个速度。

final

这个关键字很容易理解,它就是声明这个类不能被继承。


class test final{
    
       
};
 
//这行会报错,因为test不能被继承
class test_son : public test{
 
}

那么还有一个用处,就是用在虚函数上,表示不能被重写


class test{
    
    public:
        vritual int add(int a) final{}
       
};

子类继承以后就不能重写test虚函数add了,用来限定一些方法,如基类指向子类指针时,如果子类重写了(即同名函数)该方法,那么父类会优先调用子类,这样的话就是限定子类的某些行为,达到使用父类指针指向子类这样的多态性写法时,永远只能调用父类的这个方法。

到此这篇关于c++11 类中关于default、explict、implicit、noexcept、final的详解的文章就介绍到这了,更多相关c++11 类default、explict、implicit、noexcept、final内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

c++11 类中关于default、explict、implicit、noexcept、final的详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录