C++关于构造函数的一点小思考
关于构造函数
构造函数在OOP中是一切的基石,是一个类生成对象所要调用的第一个函数。
当类对象被创建时,编译器为对象分配内存空间,同时构造函数被调用。
构造函数和类名保持一致,它没有返回值,同时也不能被声明为void类型。通常,构造函数被用来对类的数据成员进行初始化。
C++的构造函数
假设我们有一个Circle类
class Circle{
Circle(){
//......
}
Circle(double radius){
//......
}
};
我们用C++的方式去声明一个对象:
Circle circle1; //无参构造函数
Circle circle2(1.0); //有参构造函数
当然,这样的方式很好理解,Circle作为一个类,可以被认为是一种数据类型,对变量进行声明和初始化的操作,这也是C语言一直以来的风格。
然而,我们和Java的对象声明进行一个比较:
Circle circle1 = new Circle(); //无参构造函数
Circle circle2 = new Circle(1.0); //有参构造函数
在这里,第一个Circle可以看作是数据类型,它声明了一个变量circle1;右值则使用new运算符申请了内存空间,并调用了Circle类的构造函数Circle(),构造出了一个对象,将其赋给circle1变量。
虽然写起来比C++多了不少,但是每一步都一目了然。再回过头来看C++的构造。
Circle circle1;
这条语句实际上隐式调用了Circle类的无参构造函数,等同于下面这条语句:
Circle circle1 = Circle(); //显示调用无参构造函数
而一个初学者总是搞不清的点在于,Circle circle1这条语句一定!一定!一定!不能加括号!
也就是说 ==Circle circle1();==这条语句是绝对错误的,因为编译器会把它看作是一个返回值为Circle类型的无参函数的声明!
然而对于有参构造函数,C++的使用如下:
Circle circle2(1.0);
那么有参构造函数就不会被编译器认为是函数声明吗?
当然不会,函数的声明必须指定形参,括号里是一个实参1.0,因此编译器不会将它错认为是函数声明。
但是这一点就很让人恼火了,无参构造函数不能带括号,有参构造函数必须带括号(否则哪里存放参数?),且当你显示调用无参构造函数的时候,又必须在构造函数Circle后面再带上括号…
从C语言起家的C++为了兼容性,保留了大部分C语言的语法,导致了各种初始化方式的鱼龙混杂。
C++标准委员会大概也觉得这样不爽,希望创造出一个大一统的方式出来,因此对于C++中的内置数据类型你都可以使用括号的方式进行初始化
比如:
int a(1);
通常你可以在构造函数的初始化列表中见到它:
class Circle{
public:
int a;
double b;
Circle() :a(1),b(1.0){
//......
}
};
总结
好了 ,最后我们对C++的构造函数的各种方法进行一个总结,只是列举一些常用的形式,没有进行深度的分析,有兴趣的读者可以自行搜索。
Circle circle1; //无参构造
Circle circle2(100); //有参构造
Circle circle3 = Circle(100); //显示调用有参构造+匿名对象
Circle circle4 = 100; //隐式调用、隐式转换
Circle circle5(Circle(100)); //等价于Circle circle5 = Circle(100);
你学废了吗?
本文是作者作为一个初学C++的小白,在学习过程中的一些心得体会和一些理解。
本人水平有限,理解错误或者不到位的地方欢迎各位大佬批评指正!