转载:果冻虾仁
提出疑问
当我们新建了一个Qt的widgets应用工程时。会自动生成一个框架,包含了几个文件。
其中有个mainwindow.h的头文件。就是你要操纵的UI主界面了。我们看看其中的一段代码:
1 class MainWindow : public QMainWindow 2 { 3 Q_OBJECT//一个宏,暂不考虑 4 5 public: 6 explicit MainWindow(QWidget *parent = 0); 7 ~MainWindow(); 8 9 private: 10 Ui::MainWindow *ui; 11 };
这段代码定义了一个新的类MainWindow,继承自QMainWindow。我们可以看到在它的构造函数里,前面有一个关键字 explicit 。
相信大家都对没有这个关键字的构造函数不陌生。那么这个 explicit 是起到什么作用的呢?
explicit研究
1 double a = 12.34; 2 int b = (int)a;
我们都知道这时b的值是12. 在变量前面加括号包裹的类型,就能实现显式的类型转换。这种叫做强制类型转换。
顺便值得一提的是,C++中还支持这种强制类型转换的例子:
1 double a = 12.34; 2 int b = int(a);
除此之外,还有一种转换叫做 隐式类型转换。
1 double a = 12.34; 2 int b = a;
同样的,b的值也是12.虽然没有显式的转换类型,但是编译器会帮你自动转换。同样的,不仅是基本数据类型,自己定义的类和对象之间也存在这种转换关系。
隐式转换的场景
等于号与构造函数
1 class A 2 { 3 public: 4 A(int i) 5 { 6 a = i; 7 } 8 int getValue() 9 { 10 return a; 11 }; 12 private: 13 int a; 14 };
你会发现,你在main函数中,使用下面的语句时是合法的:
1 A a; 2 a = 10;
注意当你使用A a = 10;时并不会产生中间的临时对象。而是直接把10作为参数传递给类型转换构造函数。
1 A a = "123";
因为没有参数为字符串的单参数构造函数。知道了这个,你修改一下就能通过了。
1 class A 2 { 3 public: 4 A(int i) 5 { 6 a = i; 7 } 8 A(char * c) 9 { 10 a=c[0]; 11 } 12 int getValue() 13 { 14 return a; 15 }; 16 private: 17 int a; 18 };
函数调用
1 void print(A a) 2 { 3 cout<<a.getValue(); 4 };
在main函数中:
1 void main() 2 { 3 print(10); 4 }
这样是可以编译运行的。虽然我们并没有创建一个类A的对象来传给print 函数。但是编译器默认会调用类A的单参数构造函数,创建出一个类A的对象出来。
加上explicit
1 public: 2 explicit A(int i) 3 { 4 a=i; 5 }
1 print(A(10));
一般而言,显示调用构造器,能避免一些麻烦,让程序员手动来管理。很多人说C++难,因为很多东西对于程序员来说不是透明的,比如内存释放什么的,这个显式调用也是需要程序员自己动手的。然而我感觉这正是C++的魅力所在,C++给了程序员几乎等同于上帝的权力,所有一切都能自己掌控,还比如运算符重载的权力,甚至像Qt这样可以自定义slot和signal关键字(其实是宏),这在其他高级语言里是不可想象的。当然了,语言这东西,是仁者见仁智者见智的。没必要争论优劣。我一直认为的是:没有最优秀的语言,只有最合适的语言。编程语言本身没有优劣之分,但是不同程序员对于不同语言确有好恶之别。
顺便一提
explicit关键字只用在类内部的声明中。在外部的实现部分不需要使用。
1 #include<iostream> 2 using namespace std; 3 class A 4 { 5 public: 6 explicit A(int i); 7 A(char * c) 8 { 9 a=c[0]; 10 } 11 int getValue() 12 { 13 return a; 14 }; 15 private: 16 int a; 17 }; 18 A::A(int i)//无需再指明explicit 19 { 20 a=i; 21 } 22 void print(A a) 23 { 24 cout<<a.getValue(); 25 }; 26 void main() 27 { 28 print(A(10)); 29 }