首先,对于创建一个对象:
1.开辟出一块空间
2.往里面填充一些垃圾值
3.使用构造函数对对象进行初始化
这里根据写法不同编译器会选择调用普通构造函数,或者拷贝构造函数或者赋值函数进行初始化,但是使用每种方式都要避免踩到相应的坑,比如使用普通构造函数就会遇到的问题。
首先,对于使用普通构造函数进行初始化对象,一般有两种方式:
1.
A a = A();//调用默认构造函数
A a = A(xx);//调用带参的构造函数
A a(xx);//调用带参的构造函数的简写形式
A a;//调用默认构造函数的简写形式
2.
使用初始化列表的方式调用构造函数
但是如果出现下面的的情况:
-
class Complex{
-
public:
-
Complex(double r, double i=0)
-
:m_real(r), m_imag(i){
-
cout<<"constructor function:"<<endl;
-
cout<<"m_real = "<<m_real<<" m_imag = "<<m_imag<<endl;
-
}
-
Complex(){
-
cout<<"No-argument constructor function:"<<endl;
-
}
-
friend void print(Complex c);
-
private:
-
double m_real;
-
double m_imag;
-
};
-
void print(Complex c){
-
cout<<"m_real = "<<c.m_real<<" m_imag = "<<c.m_imag<<endl;
-
}
-
int main(int argc, char *argv[])
-
{
-
Complex c1 = 5;
-
Complex c2;
-
c2 = 4;
-
print(10);
-
return 0;
-
}
这个时候就出现了complex c1=5的这种写法,这种写法就等于发生了一次隐式转换,即由int型隐式转换成了一个对象类型,那么是怎么发生这种转换的呢,是由于构造函数中存在单个参数造成的:
-
Complex(double r, double i=0)
-
:m_real(r), m_imag(i){
-
cout<<"constructor function:"<<endl;
-
cout<<"m_real = "<<m_real<<" m_imag = "<<m_imag<<endl;
-
}
此时编译器默认将Int类型当成5传进去构造出了一个对象。
这种写法有时候会造成一些错误:
-
#include <iostream>
-
using namespace std;
-
class MyString{
-
public:
-
MyString(int size){} //构造函数
-
MyString(const char* s=NULL){}//构造函数2
-
};
-
int main(){
-
MyString s1 = 'a';//这里原意是想用字符串"a"初始化s1,
-
//结果不小心将双引号""打成单引号''
在这种情况下,本来想创建一个对象s1,并给其初始化为a,即此时想要调用构造函数2,但是因为失误,而正好,有构造函数1满足条件被调用,就创建了97个空字符串对象,这显然是不对的。
所以对于单参的构造函数,容易发生隐式转化,避免的方法加上explicit关键字。
这种写法容易违背本身创建对象的目的,应该尽量避免。