explicit&&assert&&

本文详细解释了C++中explicit关键字的作用及注意事项,通过实例展示了如何使用explicit关键字来防止类的构造函数发生隐式类型转换,并提供了防止隐式类型转换的代码示例。

explicit作用:

在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。

explicit使用注意事项:

    *

      explicit 关键字只能用于类内部的构造函数声明上。

    *

      explicit 关键字作用于单个参数的构造函数。

    * 在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换

例子:

未加explicit时的隐式类型转换

   1. class Circle 
   2. { 
   3. public: 
   4.     Circle(double r) : R(r) {} 
   5.     Circle(int x, int y = 0) : X(x), Y(y) {} 
   6.     Circle(const Circle& c) : R(c.R), X(c.X), Y(c.Y) {} 
   7. private: 
   8.     double R; 
   9.     int    X; 
  10.     int    Y; 
  11. }; 
  12.  
  13. int _tmain(int argc, _TCHAR* argv[]) 
  14. { 
  15. //发生隐式类型转换 
  16. //编译器会将它变成如下代码 
  17. //tmp = Circle(1.23) 
  18. //Circle A(tmp); 
  19. //tmp.~Circle(); 
  20.     Circle A = 1.23;  
  21. //注意是int型的,调用的是Circle(int x, int y = 0) 
  22. //它虽然有2个参数,但后一个有默认值,任然能发生隐式转换 
  23.     Circle B = 123; 
  24. //这个算隐式调用了拷贝构造函数 
  25.     Circle C = A; 
  26.      
  27.     return 0; 
  28. } 

加了explicit关键字后,可防止以上隐式类型转换发生

   1. class Circle 
   2. { 
   3. public: 
   4.     explicit Circle(double r) : R(r) {} 
   5.     explicit Circle(int x, int y = 0) : X(x), Y(y) {} 
   6.     explicit Circle(const Circle& c) : R(c.R), X(c.X), Y(c.Y) {} 
   7. private: 
   8.     double R; 
   9.     int    X; 
  10.     int    Y; 
  11. }; 
  12.  
  13. int _tmain(int argc, _TCHAR* argv[]) 
  14. { 
  15. //一下3句,都会报错 
  16.     //Circle A = 1.23;  
  17.     //Circle B = 123; 
  18.     //Circle C = A; 
  19.      
  20. //只能用显示的方式调用了 
  21. //未给拷贝构造函数加explicit之前可以这样 
  22.          Circle A = Circle(1.23); 
  23.         Circle B = Circle(123); 
  24.         Circle C = A; 
  25.  
  26. //给拷贝构造函数加了explicit后只能这样了 
  27.          Circle A(1.23); 
  28.         Circle B(123); 
  29.         Circle C(A); 
  30.     return 0; 
  31. } 

当你涉及到将有符号整数(例如`int`)转换为无符号整数(如`unsigned int`)时,可能会遇到一些意外的行为,特别是在处理负数值的情况下。 ### `explicit`关键字的作用 `explicit` 关键字用于防止隐式类型转换导致的潜在错误。通常它会被放在构造函数前面,表明这个构造函数只能通过显式的调用来创建对象,而不能通过隐含的类型转换操作来进行实例化。 然而,在 C++ 中,并不存在直接与 "解决 unsigned 输入负数" 相关的标准库特性或语言特性的场景下使用 `explicit` 的情况。你提到的问题更可能是关于如何安全地从 signed 类型向 unsigned 类型赋值。 当一个负数被赋予给 unsigned 变量时,默认情况下该值将会按照模运算规则解释成非常大的正数 (即加上了相应的最大取值范围后的结果)。这种行为虽然符合标准但往往不是我们期望的结果。 为了更好地理解和避免这种情况的发生: #### 使用静态断言检查 可以在编译期加入对传入参数是否小于零做判断,如果违反则报错: ```cpp #include <type_traits> // ... void acceptUnsigned(unsigned value){ static_assert(std::is_unsigned<decltype(value)>::value,"Parameter must be an unsigned type"); } ``` #### 手动验证并抛出异常 运行期间检测输入是不是有效的非负整数: ```cpp unsigned convertToInt(const int input) { if(input<0) throw std::invalid_argument("Negative numbers cannot converted to unsigned."); return static_cast<unsigned>(input); } ``` 如果你确实希望利用某种机制使得这类转化变得更明确、减少误用的风险,你可以考虑设计自定义包装类来管理此类数据类型的转变过程;同时也可以借助现代C++提供的工具比如强枚举等手段增强程序的安全性和表达力。 对于这个问题本身来说,`explicit` 并不是一个合适的解决方案,因为这不是由构造函数引起的自动转型问题而是基本类型的默认语义所致的现象。 --
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值