构造函数的分类和调用
分类
默认构造函数、无参构造函数、有参构造函数、赋值(拷贝)构造函数
class Test
{
private:
int a;
public:
// 默认无参构造函数:当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
//Test()
//{
//}
// 默认赋值构造函数(拷贝构造函数):类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制
//Test(const Test &obj)
//{
// this->a = obj.a;
//}
Test()// 无参数构造函数,覆盖编译器提供的默认构造函数
{
this->a = 10;
}
Test(int a)// 有参数构造函数
{
this->a = a;
}
Test(const Test &obj)// 赋值构造函数(拷贝构造函数),覆盖编译器提供的默认赋值构造函数
{
this->a = obj.a + 100;
}
~Test()// 析构函数
{
cout << "调用了对象的析构函数" << endl;
}
};
无参构造函数
#include <iostream>
using namespace std;
class Test
{
private:
int a;
public:
Test()// 无参数构造函数
{
this->a = 10;
}
~Test()
{
cout << "调用了对象的析构函数" << endl;
}
void printA()
{
cout << "a = "<< this->a << endl;
}
};
void main() {
Test t1;
//Test t2();// 错误的调用方式,不需要加()
t1.printA();
cout << "Done......" << endl;
system("pause");
}
有参构造函数
#include <iostream>
using namespace std;
class Test
{
private:
int a;
public:
Test(int a)// 有参数构造函数
{
this->a = a;
}
~Test()
{
cout << "调用了对象的析构函数" << endl;
}
void printA()
{
cout << "a = "<< this->a << endl;
}
};
void main() {
Test t1(1);// C++自动调用构造函数
Test t2 = 2;// C++自动调用构造函数
Test t3 = { 3 };// C++自动调用构造函数
Test t4 = Test(4);// 程序员手动的调用构造函数(生成匿名对象,直接转化成t4)
t1.printA();
t2.printA();
t3.printA();
t4.printA();
cout << "Done......" << endl;
system("pause");
}
赋值(拷贝)构造函数
作用:用一个对象初始化另外一个同类对象
#include <iostream>
using namespace std;
class Test
{
private:
int a;
public:
Test()
{
this->a = 10;
}
Test(const Test &obj)// 赋值构造函数(拷贝构造函数)
{
this->a = obj.a + 100;
}
~Test()
{
cout << "调用了对象的析构函数" << endl;
}
void printA()
{
cout << "a = "<< this->a << endl;
}
};
void main() {
Test t1;
Test t2 = t1;// C++编译器自动调用拷贝构造函数
Test t3 = Test(t2);// 程序员手动调用拷贝构造函数
t1.printA();
t2.printA();
t3.printA();
cout << "Done......" << endl;
system("pause");
}
赋值构造函数的四种应用场景
第一、第二种应用场景:对象初始化
Test t1;
Test t2 = t1;// C++编译器自动调用拷贝构造函数
Test t3 = Test(t2);// 程序员手动调用拷贝构造函数
第三种应用场景:实参传递值给形参
#include <iostream>
using namespace std;
class Test
{
private:
int a;
public:
Test()
{
this->a = 10;
}
Test(const Test &obj)// 赋值构造函数(拷贝构造函数)
{
this->a = obj.a + 100;
}
~Test()
{
cout << "调用了对象的析构函数" << endl;
}
void printTest(const Test t)
{
cout << t.a << endl;
}
};
void main() {
Test t1;
Test t2;
t1.printTest(t2);// t2实参去初始化形参t,会调用Test的拷贝构造函数完成t的初始化
cout << "Done......" << endl;
system("pause");
}
第四种应用场景:匿名对象
#include <iostream>
using namespace std;
class Test
{
private:
int a;
public:
Test()
{
this->a = 10;
}
Test(const Test &obj)// 赋值构造函数(拷贝构造函数)
{
this->a = obj.a + 100;
}
~Test()
{
cout << "调用了对象的析构函数" << endl;
}
// 返回一个匿名对象
Test getTestObj()
{
Test t;
return t;
}
};
void main() {
Test t1;
Test t2 = t1.getTestObj();// 用匿名对象初始化另外一个对象,匿名对象直接(扶正)转化为t2对象
Test t3;
t3 = t1.getTestObj();// 用匿名对象给另外一个已存在的对象t3赋值,赋值完成以后匿名对象被析构掉
cout << "Done......" << endl;
system("pause");
}
初始化与赋值的根本差别
截图自《C++ Primer Plus 第6版》
站在C++编译器的角度分析问题,如果用匿名对象初始化另一个对象,不用再进行如给新对象分配内存空间,将匿名对象的值拷贝给新对象,析构匿名对象等等这一系列耗内存影响性能的操作,直接将匿名对象的内存地址给新对象效率更高。