我将c++ 类构建对象的方式分为两类:
1、显示调用构造函数,构造对象如:
class A{
public:
A() //默认的无参构造函数
{}
A(int)
{}
A(const A& ) //拷贝构造函数,如果不定义,则使用编译器自己生成的拷贝构造函数(为浅拷贝)
{}
};
A a(56); //显示调用带int参数的构造函数
A a1(a); //显示调用拷贝构造函数
2、通过带一个参数的构造函数具有隐式转换功能,来调用构造函数,初始化对象。
class A{
public:
A() //默认的无参构造函数
{}
A(int)
{}
A(const A& ) //拷贝构造函数,如果不定义,则使用编译器自己生成的拷贝构造函数(为浅拷贝)
{}
};
A a = 5; // 5是int型,并不是class A 类型.由于带一个参数的构造函数具有隐式转换功能,所以,编译器会将int型的5转换成临时对象A(5)来构造对象a;
A b = a; //a是class A 类型,编译器将会调用A(a)生成临时对象来构造b;
附加:使用临时的无名对象来构造新对象时,并不会调用拷贝构造函数,而是将旧的临时的无名对象换成新的有名对象。这样做可以加长临时对象的生存期。
注意:如果构造函数里加上explicit 修饰了,则该构造函数只能显示调用,不具备隐式转换的功能。
另外:c++里构造函数不能用static或virtual关键字进行修饰
为什么不能用virtual修饰?
因为执行虚函数时,会通过指向虚函数表的指针(vptr)调用表中的虚函数,而虚函数表只有在对象构建成功后,该类含有虚函数则会存在虚函数表。
所以,如果用virtual修饰构造函数,那么此时,对象都没有构造成功,虚函数表都不存在。也就不能调用虚方法。所以构造函数不能用virtual修饰
vptr指针指向虚函数表,执行虚函数的时候,会调用vptr指针变量指向的虚函数表中的虚函数。 当定义个对象的时候,首先会分配内存空间,然后再执行构造函数对该对象进行初始化构造。vptr变量是在构造函数中进行初始化的。又因为要想执行虚函数必须通过vptr变量找到虚函数表。
class A{
public:
A()
{}
explicit A(int)
{}
explicit A(const A& )
{}
};
此时, A a ;//正确
A b(5); //正确
A c(a); //正确 均显示调用构造函数
但是 A d = a;//则,编译错误,找不到匹配的构造函数。
A e = 5 ; //错误;
什么时候调用拷贝构造函数,和调用=(赋值运算符)方法?
拷贝构造函数也是构造函数;1.在构造对象时,调用;2.拷贝构造函数是带一个参数的构造函数具有隐式转化功能,在需要隐式转化时,会调用。
调用赋值运算符(=)只有在赋值时才会使用。只有数据类型相同,或者数据类型能隐式转化,或者重载了赋值运算符的情况下才能使用正常。
下面是例子:
class student
{
public:
int sno;
student (int sno):sno(sno)
{}
student(const student& s)
{
printf("aaaaaaaaaaaaa\n");
}
~student()
{}
/*
void operator=(int a)
{
sno=a;
}
*/
};
int main()
{
student s=10;//由于有带一个int参数的构造函数,先将10隐式转化成student(10)临时无名对象,在使用临时无名对象初始化对象;(就是将临时的无名的对象换成新的有名的对象)
s=100;//如果没用重载赋值运算符,就会先调用构造函数student(100),生成临时无名对象(此时数据类型相同),再赋值。
//上面是重载=运算符了,就直接调用重载的=运算符
return 0;
}
注意:构造函数也可以用private、protected、public修饰和普通方法用他们修饰一样
private修饰构造函数,只允许在类里使用该构造函数即(只能在类里构造对象,单例模式)
protected修饰构造函数,允许在类里和派生类中使用,如:
class A { protected: A() { printf("aaa\n"); } }; class B:public A { public: B() { printf("bbbb\n"); } };
class C:public A{public: C():A(){printf("CCCC\n");}};
public修饰则可以在类外和派生类或者类里使用
