C++的一些好用的限定修饰符

引入

在java中有一种代码审查机制叫做javaDoc机制;
他通过在java的函数前面加上@关键字 的方式来限定函数只能做什么样的功能;
这可以有效地防止我们编码的时候出现一些小错误导致代码功能的问题;
C++中也有相应的机制~~,让我们深入了解修饰符的魅力吧

比较常见的操作就像我们声明get方法的时候会在后面加上const关键字限定,这个可以防止函数修改调用他的对象的值;
我之前就犯过在if中将== 写成了=的错误,但是只要加上这个限定编译器就立马发现你修改了这个值!!!非常好用!!!

explicit关键字

这个关键字是用来禁止参数隐式转换的;而且它只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).

首先我们看看例子:

class CxString  // 没有使用explicit关键字的类声明, 即默认为隐式声明  
{  
public:  
    char *_pstr;  
    int _size;  
    CxString(int size)  
    {  
        _size = size;                // string的预设大小  
        _pstr = malloc(size + 1);    // 分配string的内存  
        memset(_pstr, 0, size + 1);  
    }  
    CxString(const char *p)  
    {  
        int size = strlen(p);  
        _pstr = malloc(size + 1);    // 分配string的内存  
        strcpy(_pstr, p);            // 复制字符串  
        _size = strlen(_pstr);  
    }  
    // 析构函数这里不讨论, 省略...  
};  
  
    // 下面是调用:  
  
    CxString string1(24);     // 这样是OK的, 为CxString预分配24字节的大小的内存  
    CxString string2 = 10;    // 这样是OK的, 为CxString预分配10字节的大小的内存  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码  
    string1 = 2;              // 这样也是OK的, 为CxString预分配2字节的大小的内存  
    string2 = 3;              // 这样也是OK的, 为CxString预分配3字节的大小的内存  
    string3 = string1;        // 这样也是OK的, 至少编译是没问题的, 但是如果析构函数里用free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放  

当你有多个重载的构造函数时,如果不加explicit关键字,会导致出现CxString string2 = 10;这种隐式的类型转换也是可以的,编译器会自动将整型转换为CxString类对象,这种操作是非常容易带来一些不易找到的bug

我们加上explicit之后就不会有这种隐式转换,为我们的编码安全提供了保障。

class CxString  // 使用关键字explicit的类声明, 显示转换  
{  
public:  
    char *_pstr;  
    int _size;  
    explicit CxString(int size)  
    {  
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {  
        // 代码同上, 省略...  
    }  
};  
  
    // 下面是调用:  
  
    CxString string1(24);     // 这样是OK的  
    CxString string2 = 10;    // 这样是不行的, 因为explicit关键字取消了隐式转换  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样是不行的, 其实调用的是CxString(int size), 且size等于'c'的ascii码, 但explicit关键字取消了隐式转换  
    string1 = 2;              // 这样也是不行的, 因为取消了隐式转换  
    string2 = 3;              // 这样也是不行的, 因为取消了隐式转换  
    string3 = string1;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载  

virtual关键字

这个关键字大家写C++的应该都很熟悉了,这是一个用于修饰虚拟成员的关键字;

在java中如果是接口interface类,这个关键字就不需要加了,JVM他会把每个函数都定义成纯虚函数。

在C++中这个关键字用法就不一样了,定义虚函数的时候

override关键字

在我们java的开发中,有这个关键字的应用;
当你实现一个接口的时候,IDEA会默认帮你加上JavaDoc的这个关键字@override
这个关键字就是这么用的,当我们重写父类方法时加上这个关键字编译器就会帮你检查你重写的参数列表正不正确;
如果派生类在虚函数声明时使用了 override 描述符,那么该函数必须 重写 其基类中的同名函数。否则代码将无法通过编译

这里有一些上述两个关键字的使用准则:

  • 基类中使用纯虚函数,则派生类则是从基类继承接口,并且必须在类中对该接口进行实现;
  • 基类中使用普通虚函数,则派生类是从基类继承接口和缺省实现,如果派生类重写该接口,则使用派生类的实现,如果没有,则使用基类的缺省实现,而override常使用在此情况中,最好建议在派生类中需要重写的函数声明之后增加关键字override,避免出现逻辑错误;
  • 基类中使用普通函数,则派生类是从基类继承接口和强制实现,不建议修改继承自基类的非虚函数;

一句话就是父类的方法要下发实现时就加上virtual,子类要重写父类方法的时候就加上virtual和override,C++中父类不想实现这个虚函数就定义成纯虚函数加上 = 0


有时间接着完善,还有很多我也没用过的修饰符,这些修饰符看似不起眼,但是它可以为你的编码工作添加助力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AlbertOS

还会有大爷会打钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值