纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

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

17岁boy想当攻城狮   2021-11-20 我要评论
想了解c++11 类中关于default、explict、implicit、noexcept、final的详解的相关内容吗17岁boy想当攻城狮在本文为您仔细讲解c++11 类default、explict、implicit、noexcept、final的相关知识和一些Code实例欢迎阅读和指正我们先划重点:c++11 类default,C++  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语言 烟花 给喜欢的人用C语言写烟花

    想了解给喜欢的人用C语言写烟花的相关内容吗MAX在码字在本文为您仔细讲解C语言 烟花的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C语言,烟花,C语言,实例下面大家一起来学习吧..
  • C语言 递归 C语言 递归解决青蛙跳台阶问题

    想了解C语言 递归解决青蛙跳台阶问题的相关内容吗愿百事可乐在本文为您仔细讲解C语言 递归的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C语言,递归,C语言,青蛙跳台下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式