
C++的构造函数是用来对对象初始化 *** 作,下面将对几种构造函数使用上进行详细说明。
默认构造函数创建对象的时候且不传递任何参数的时候自动调用
合成默认构造函数(编译器自动创建)创建对象的时候不传递任何参数,用户在程序没有定义默认函数,那么由编译器自动创建。
1)类成员数据没有类内初始值,使用默认初始化实际不做任何 *** 作。
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName();
int getClassNum();
void setAddr();
private: // 保护类内属性
string className;
char* addr;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr() {
}
int main() {
Cls c1; // 此时调用合成默认参数构造函数
cout << c1.getClassNum() << endl;
system("pause");
return 0;
}
输入、输出:
0
结论:没有任何意义的默认构造函数
2)当类内数据有初始化的值时,编译器创建的合成默认构造使用这个值对创建的对象初始化。
类内初始值在C++11及以上的标准才支持
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName();
int getClassNum();
void setAddr();
private: // 保护类内属性
// 类内数据有初始值
string className = "大班";
char* addr = NULL;
int classNum = 12;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr() {
}
int main() {
Cls c1; // 此时调用合成默认参数构造函数,并且把类内初始化值拿来给对象初始化
cout << c1.getClassNum() << endl;
cout << c1.getClassName() << endl;
system("pause");
return 0;
}
输入、输出:
12
大班
结论:当类内数据全部都使用了初始值,然后使用合成默认构造函数才有意义
用户定义默认构造函数手动定义的默认构造函数是最好的,因为规范化的时候类内初始是不存在的。所以我们创建对象的时候一般通过默认构造函数来进行数据初始化。
代码:
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName();
int getClassNum();
void setAddr();
// 自定义默认构造函数:没有返回值和类名相同
Cls();
private: // 保护类内属性
string className;
char* addr;
// 当自定义默认构造函数也修改了改数据,那么该类内初始值既被覆盖
int classNum = 12;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr() {
}
// 使用自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = NULL;
classNum = 13;
}
int main() {
Cls c1; // 此时调用自定义默认参数构造函数,然后对对象初始
cout << c1.getClassNum() << endl; // 用户自定义初始化值。覆盖了类内初始值。
cout << c1.getClassName() << endl;
cout << "**************" << endl;
Cls c2; // 此时调用自定义默认参数构造函数,然后对对象初始
cout << c2.getClassNum() << endl;
cout << c2.getClassName() << endl;
system("pause");
return 0;
}
输入、输出:
自定义默认构造函数被调用
13
小班
**************
自定义默认构造函数被调用
13
结论:当某个数据成员在类内初始化后,同时也在构造函数中进行了初始化 *** 作,那么以构造函数中的为准。
相当于构造函数中的初始化,会覆盖类内初始化。
创建对象的传递参数,调用该构造函数。
自定义带参数的构造函数可以发生重载。
代码:
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName();
int getClassNum();
char* getAddr();
void setAddr();
void descrirition();
Cls(); // 自定义默认构造函数:没有返回值和类名相同
Cls(int classNum, string className, const char* addr); // 自定义参数构造函数
Cls(int classNum, string className); // 自定义参数构造函数重载
private: // 保护类内属性
string className;
char* addr = NULL;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
char* Cls::getAddr() {
return addr;
}
void Cls::setAddr() {
}
// 自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = NULL;
classNum = 11;
}
void Cls::descrirition() {
cout << "addr: " << addr
<< " className:" << className
<< "classNum:" << classNum << endl;
}
// 自定义参数构造函数
Cls::Cls(int classNum, string className,const char* addr) {
cout << "自定义参数构造函数-重载1" << endl;
this->classNum = classNum;
this->className = className;
this->addr = (char*)addr;
}
// 自定义参数构造函数重载
Cls::Cls(int classNum, string className) {
cout << "自定义参数构造函数-重载2" << endl;
this->classNum = classNum;
this->className = className;
}
int main() {
Cls c1(13, "大班");
cout << " className:" << c1.getClassName()
<< " classNum:" << c1.getClassNum() << endl;
Cls c2(12, "中班", "北京");
c2.descrirition();
system("pause");
return 0;
}
输入、输出:
自定义参数构造函数-重载2
className:大班 classNum:13
自定义参数构造函数-重载1
addr: 北京 className:中班classNum:12
结论:
1、自定义带参数构造函数用于创建对象带参数
2、自定义带参数构造函数可以发生重载
拷贝函数在什么时候被调用?
拷贝构造函数也有合成拷贝构造函数(编译器自动创建)和自定义拷贝构造函数之分。
合成拷贝构造函数是浅拷贝,而我们自定义的一般使用深拷贝。
深浅拷贝一般针对的是指针,在堆区开辟内存空间,后面程序中我们会细讲。
合成拷贝构造函数编译器自动创建,浅拷贝。
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName();
int getClassNum();
char* getAddr();
void setAddr(const char* addr);
void descrirition();
Cls(); // 自定义默认构造函数:没有返回值和类名相同
Cls(int classNum, string className, const char* addr); // 自定义参数构造函数
Cls(int classNum, string className); // 自定义参数构造函数重载
private: // 保护类内属性
string className;
char* addr = NULL;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
char* Cls::getAddr() {
return addr;
}
void Cls::setAddr(const char* addr) {
strcpy_s(this->addr, 20, addr);
}
// 自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = NULL;
classNum = 11;
}
void Cls::descrirition() {
cout << "addr: " << addr
<< " className:" << className
<< "classNum:" << classNum << endl;
}
// 自定义参数构造函数
Cls::Cls(int classNum, string className,const char* addr) {
cout << "自定义参数构造函数-重载1" << endl;
this->classNum = classNum;
this->className = className;
this->addr = new char[20];
strcpy_s(this->addr, 20, addr);
}
// 自定义参数构造函数重载
Cls::Cls(int classNum, string className) {
cout << "自定义参数构造函数-重载2" << endl;
this->classNum = classNum;
this->className = className;
}
int main() {
Cls c1(12, "中班", "北京");
// 使用已创建的对象来创建对象调用,拷贝构造函数
Cls c2 = c1; // 这里针对指针数据只是复制了地址
Cls c3(c1);
c1.descrirition();
c2.descrirition();
cout << "修改" << endl;
c1.setAddr("南京");
c1.descrirition();
c2.descrirition();
system("pause");
return 0;
}
输入、输出:
自定义参数构造函数-重载1
addr: 北京 className:中班classNum:12
addr: 北京 className:中班classNum:12
修改
addr: 南京 className:中班classNum:12
addr: 南京 className:中班classNum:12
结论:
1、编译器自动生成的合成拷贝构造函数是浅拷贝
代码:
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName(); // 获取classname
int getClassNum(); // 获取classNum
void setAddr(const char* addr); // 修改addr
void descrirition(); // 打印对象描述信息
Cls(const Cls& other); // 深浅拷贝
Cls(); // 自定义默认构造函数:没有返回值和类名相同
Cls(int classNum, string className, const char* addr); // 自定义参数构造函数
Cls(int classNum, string className); // 自定义参数构造函数重载
private: // 保护类内属性
string className;
char* addr = NULL;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr(const char* addr) {
strcpy_s(this->addr, 20, addr);
}
// 自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = NULL;
classNum = 11;
}
void Cls::descrirition() {
cout << "addr: " << addr
<< " className:" << className
<< "classNum:" << classNum << endl;
}
// 自定义参数构造函数
Cls::Cls(int classNum, string className,const char* addr) {
cout << "自定义参数构造函数-重载1" << endl;
this->classNum = classNum;
this->className = className;
this->addr = new char[20];
strcpy_s(this->addr, 20, addr);
}
// 自定义参数构造函数重载
Cls::Cls(int classNum, string className) {
cout << "自定义参数构造函数-重载2" << endl;
this->classNum = classNum;
this->className = className;
}
// 浅拷贝
Cls::Cls(const Cls& other) {
cout << "浅拷贝" << endl;
className = other.className;
classNum = other.classNum
addr = other.addr;
}
深拷贝
//Cls::Cls(const Cls& other) {
// 注意这里一定要在堆区重新开辟空间
// className = other.className;
// classNum = other.classNum
// addr = new char[20];
// strcpy_s(addr, 20, other.addr);
//}
int main() {
Cls c1(12, "中班", "北京");
// 使用已创建的对象来创建对象调用,拷贝构造函数
Cls c2 = c1;
Cls c3(c1);
c1.descrirition();
c2.descrirition();
cout << "修改" << endl;
c1.setAddr("南京");
c1.descrirition();
c2.descrirition();
system("pause");
return 0;
}
输入、输出:
自定义参数构造函数-重载1
浅拷贝
浅拷贝
addr: 北京 className:中班classNum:12
addr: 北京 className:classNum:0
修改
addr: 南京 className:中班classNum:12
addr: 南京 className:classNum:0
拷贝构造函数的调用时间
1、利用已有的对象构建新的对象
2、对象作为函数的形参,并且不是引用
3、对象作为函数返回值,并且不是引用
4、对象作为数组成员
代码:
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName(); // 获取classname
int getClassNum(); // 获取classNum
void setAddr(const char* addr); // 修改addr
void descrirition(); // 打印对象描述信息
Cls(const Cls& other); // 深浅拷贝
Cls(); // 自定义默认构造函数:没有返回值和类名相同
Cls(int classNum, string className, const char* addr); // 自定义参数构造函数
Cls(int classNum, string className); // 自定义参数构造函数重载
private: // 保护类内属性
string className;
char* addr = NULL;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr(const char* addr) {
strcpy_s(this->addr, 20, addr);
}
// 自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = NULL;
classNum = 11;
}
void Cls::descrirition() {
cout << "addr: " << addr
<< " className:" << className
<< "classNum:" << classNum << endl;
}
// 自定义参数构造函数
Cls::Cls(int classNum, string className,const char* addr) {
cout << "自定义参数构造函数-重载1" << endl;
this->classNum = classNum;
this->className = className;
this->addr = new char[20];
strcpy_s(this->addr, 20, addr);
}
// 自定义参数构造函数重载
Cls::Cls(int classNum, string className) {
cout << "自定义参数构造函数-重载2" << endl;
this->classNum = classNum;
this->className = className;
}
// 浅拷贝
//Cls::Cls(const Cls& other) {
// cout << "浅拷贝" << endl;
// className = other.className;
// classNum = other.classNum;
// addr = other.addr;
//}
// 深拷贝
Cls::Cls(const Cls& other) {
cout << "深拷贝" << endl;
className = other.className;
classNum = other.classNum;
// 注意这里一定要重新在堆区创建空间
addr = new char[20];
strcpy_s(addr, 20, other.addr);
}
// 对象作为函数参数
void getMeag(Cls c) {
c.descrirition();
}
// 对象作为函数返回值
Cls clsReturn(Cls& c1, Cls& c2) {
if (c1.getClassNum() >= c2.getClassNum()) {
return c1;
}
else return c2;
}
int main() {
Cls c1(12, "中班", "北京");
// 1、使用已创建的对象来创建对象调用拷贝构造函数
Cls c2 = c1;
Cls c3(c1);
c1.descrirition();
c2.descrirition();
cout << "修改" << endl;
c1.setAddr("南京");
c1.descrirition();
c2.descrirition();
// 2、作为函数形参
getMeag(c1);
// 3、作为函数返回值
clsReturn(c1, c2);
//4、作为数组成员
Cls C3[3] = {c1, c2, c3}; // C3[0]=c1 ....C3[2]=c3
system("pause");
return 0;
}
输入、输出:
自定义参数构造函数-重载1
深拷贝
深拷贝
addr: 北京 className:中班classNum:12
addr: 北京 className:中班classNum:12
修改
addr: 南京 className:中班classNum:12
addr: 北京 className:中班classNum:12
深拷贝
addr: 南京 className:中班classNum:12
深拷贝
深拷贝
深拷贝
深拷贝
总结:
1、四种拷贝构造函数被调用时间
2、深浅拷贝
3、对象作为函数返回值和参数的时候,如果不是引用。那么会拷贝一份对象,占用内存空间。
对象创建完毕以后出现对象和对象赋值,会调用赋值构造函数
代码:
#include
#include
#include
using namespace std;
// 类声明
class Cls {
public:
string getClassName(); // 获取classname
int getClassNum(); // 获取classNum
void setAddr(const char* addr); // 修改addr
void descrirition(); // 打印对象描述信息
Cls(const Cls& other); // 深浅拷贝
Cls(); // 自定义默认构造函数:没有返回值和类名相同
Cls(int classNum, string className, const char* addr); // 自定义参数构造函数
Cls(int classNum, string className); // 自定义参数构造函数重载
Cls& operator=(const Cls& other); // 赋值构造函数
private: // 保护类内属性
string className;
char* addr = NULL;
int classNum;
};
// 类内成员函数定义
string Cls::getClassName() {
return className;
}
int Cls::getClassNum() {
return classNum;
}
void Cls::setAddr(const char* addr) {
strcpy_s(this->addr, 20, addr);
}
// 自定义默认构造函数来进行对象初始化
Cls::Cls() {
cout << "自定义默认构造函数被调用" << endl;
className = "小班";
addr = new char[20];
classNum = 11;
}
void Cls::descrirition() {
cout << "addr: " << addr
<< " className:" << className
<< "classNum:" << classNum << endl;
}
// 自定义参数构造函数
Cls::Cls(int classNum, string className,const char* addr) {
cout << "自定义参数构造函数-重载1" << endl;
this->classNum = classNum;
this->className = className;
this->addr = new char[20];
strcpy_s(this->addr, 20, addr);
}
// 自定义参数构造函数重载
Cls::Cls(int classNum, string className) {
cout << "自定义参数构造函数-重载2" << endl;
this->classNum = classNum;
this->className = className;
}
// 赋值拷贝构造函数
Cls& Cls::operator=(const Cls& other) {
cout << "赋值拷贝构造函数" << endl;
// 防止出现c1 = c1;
if (this == &other) {
return *this;
}
className = other.className;
classNum = other.classNum;
return *this; // 链式编程 c1 = c2 = c3;
}
int main() {
Cls c1, c2;
c2 = c1;
system("pause");
return 0;
}
输入、输出:
自定义默认构造函数被调用
自定义默认构造函数被调用
赋值拷贝构造函数
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)