c++关键字explicit使用指南

来源:互联网 发布:flac mac 播放 编辑:程序博客网 时间:2024/04/29 20:16

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. } 

 

 

按照默认规定,只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应数据类型的数据转换为该类对象,如下面所示:
class String {
String ( const char* p ); // 用C风格的字符串p作为初始化值
//…
}
String s1 = “hello”; //OK 隐式转换,等价于String s1 = String(“hello”);
 
但是有的时候可能会不需要这种隐式转换,如下:
class String {
       String ( int n ); //本意是预先分配n个字节给字符串
String ( const char* p ); // 用C风格的字符串p作为初始化值
//…
}
 
下面两种写法比较正常:
String s2 ( 10 );   //OK 分配10个字节的空字符串
String s3 = String ( 10 ); //OK 分配10个字节的空字符串
 
下面两种写法就比较疑惑了:
String s4 = 10; //编译通过,也是分配10个字节的空字符串
String s5 = ‘a’; //编译通过,分配int(‘a’)个字节的空字符串
 
s4 和s5 分别把一个int型和char型,隐式转换成了分配若干字节的空字符串,容易令人误解。
为了避免这种错误的发生,我们可以声明显示的转换,使用explicit 关键字:
class String {
       explicit String ( int n ); //本意是预先分配n个字节给字符串
String ( const char* p ); // 用C风格的字符串p作为初始化值
//…
}
加上explicit就抑制了String ( int n )的隐式转换,
 
下面两种写法仍然正确:
String s2 ( 10 );   //OK 分配10个字节的空字符串
String s3 = String ( 10 ); //OK 分配10个字节的空字符串
 
下面两种写法就不允许了:
String s4 = 10; //编译不通过,不允许隐式的转换
String s5 = ‘a’; //编译不通过,不允许隐式的转换
 
因此,某些时候,explicit 可以有效得防止构造函数的隐式转换带来的错误或者误解

----------------------------------------------------------
explicit   只对构造函数起作用,用来抑制隐式转换。如:  
  class   A   {  
          A(int   a);  
  };  
  int   Function(A   a);  
   
  当调用   Function(2)   的时候,2   会隐式转换为   A   类型。这种情况常常不是程序员想要的结果,所以,要避免之,就可以这样写:  
   
  class   A   {  
          explicit   A(int   a);  
  };  
  int   Function(A   a);  
   
  这样,当调用   Function(2)   的时候,编译器会给出错误信息(除非   Function   有个以   int   为参数的重载形式),这就避免了在程序员毫不知情的情况下出现错误。

总结:explicit   只对构造函数起作用,用来抑制隐式转换。

 

原创粉丝点击