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