构造函数
1 C++的类可以定义与类名相同的特殊函数,这种与类名相同的函数叫做构造函数
2 构造函数在定义时可以有参数
3 没有返回类型声明
析构函数
特殊的成员函数清理对象,析构函数
语法:~className()
析构函数没有参数,没有返回类型声明
析构函数在对象销毁时自动被调用
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public:
// 无参数 构造函数
Test() {
a = 10; // 完成对属性的初始化
p = (char*)malloc(100);
strcpy(p, "abcdefg");
cout << "构造函数" << endl;
}
void printP() {
cout << p << endl;
cout << a << endl;
}
// 析构时先创建时后释放
~Test() {
if (p != NULL) {
free(p);
}
cout << "析构函数" << endl;
}
private:
int a;
char* p;
};
void objplay() {
Test t1;
t1.printP();
cout << "-------------" << endl;
Test t2;
t2.printP();
}
int main() {
objplay();
return 0;
}
构造函数的三种调用方法
1 括号法
2 等号法
3 直接法
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public:
// 无参数 构造函数
Test() {
cout << "无参构造函数" << endl;
}
Test(int a) {
m_a = a;
m_b = 0;
}
Test(int a, int b) {
m_a = a;
m_b = b;
cout << "有参构造函数" << endl;
}
//赋值构造函数
Test(const Test& obj) {
cout << "赋值、拷贝构造函数" << endl;
}
void printT() {
cout << "普通成员函数" << endl;
}
private:
int m_a;
int m_b;
/*int a;
char* p;*/
};
int main() {
// Test t1; // 调用无参数构造函数
Test t1(1, 2); // 调用有参构造函数(括号法) c++编译器调用
t1.printT();
cout << "-------------" << endl;
Test t2 = (3, 4); //逗号表达式,最后一个值 4(等号法) c++编译器调用
Test t3 = 5;
Test t4 = Test(1, 2); // 手动调用 产生一个匿名对象(匿名对象的去留问题) t4对象初始化
// 对象初始化和对象的赋值
t1 = t4; // 把t4拷贝给t1 赋值操作
return 0;
}
初始化用途
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public:
void init(int _a, int _b) {
a = _a;
b = _b;
}
private:
int a;
int b;
};
void main() {
// 类没有提供构造函数,c++编译器会自动提供一个默认的构造函数
// 类没有提供构造函数 拷贝构造函数, C++编译器会自动给程序员提供一个默认的拷贝构造函数
Test t1;
int a = 10;
int b = 20;
t1.init(a, b);
Test t21; t21.init(1, 2);
Test t22; t22.init(1, 2);
Test t23; t23.init(1, 2);
// 这种场景下,显式初始化难以使用
Test tArray[3] = { t21, t22, t23 };
/*Test tArray[3];
tArray[0].init(1, 2);
tArray[1].init(1, 2);
tArray[2].init(1, 2);*/
}
赋值(copy)构造函数四种调用时机
用一个对象初始化另外一个对象
第一种方法
class Test {
public:
// 无参数 构造函数
Test() {
cout << "无参构造函数" << endl;
}
Test(int a) {
m_a = a;
m_b = 0;
}
Test(int a, int b) {
m_a = a;
m_b = b;
cout << "有参构造函数" << endl;
}
//赋值构造函数
Test(const Test& obj) {
cout << "赋值、拷贝构造函数" << endl;
m_a = obj.m_a + 100; // 可以更改拷贝构造
m_b = obj.m_b + 100;
}
void printT() {
cout << "普通成员函数" << endl;
cout << "m_a" << m_a << endl;
cout << "m_b" << m_b << endl;
}
private:
int m_a;
int m_b;
/*int a;
char* p;*/
};
int main() {
Test t0(1, 2);
Test t1(1, 2);
t0 = t1; //用t1给t0赋值 赋值和初始化是两个不同的概念
// 第一种拷贝构造调用方法
Test t2 = t1; // 用t1初始化t2
t2.printT();
}
第二种拷贝构造调用方法
int main() {
Test t0(1, 2);
Test t1(1, 2);
t0 = t1; //用t1给t0赋值 赋值和初始化是两个不同的概念
//第二种拷贝构造调用方法
Test t2(t1); // 用t1初始化t2
t2.printT();
}
第三种拷贝构造函数调用方法(函数形参)
// copy 构造函数
class Location {
public:
Location(int xx = 0, int yy = 0) {
X = xx;
Y = yy;
cout << "构造函数" << endl;
}
// copy构造函数 完成对象初始化
Location(const Location& obj) {
X = obj.X;
Y = obj.Y;
}
~Location() {
cout << X << "," << Y << "析构函数" << endl;
}
int GetX() { return X; }
int GetY() { return Y; }
private:
int X;
int Y;
};
// 形参是元素
void f(Location p) {
cout << p.GetX() << endl;
}
void printobj() {
Location a(1, 2);
Location b = a;
cout << "b对象已经初始化完毕" << endl;
f(b); // b实参初始化形参p,调用copy构造函数
}
void main() {
printobj();
}
第四种拷贝构造函数调用方式
class Location {
public:
Location(int xx = 0, int yy = 0) {
X = xx;
Y = yy;
cout << "构造函数" << endl;
}
// copy构造函数 完成对象初始化
Location(const Location& obj) {
X = obj.X;
Y = obj.Y;
}
~Location() {
cout << X << "," << Y << "析构函数" << endl;
}
int GetX() { return X; }
int GetY() { return Y; }
private:
int X;
int Y;
};
// 形参是元素
void f(Location p) {
cout << p.GetX() << endl;
}
// g函数返回一个元素
// 函数的返回值是一个元素(复杂类型的) 返回的是一个新的匿名对象 调用匿名对象类的copy构造函数
// 默认返回一个新对象(匿名对象)
// 如果匿名对象初始化给另外一个同类型的对象,匿名对象转化为有名对象
// 如果匿名对象赋值给另外一个同类型的对象,匿名对象被析构
Location g() {
Location A(1, 2); // 调用一般构造函数
return A; // 调用copy构造函数 生成匿名对象
// 最终两个对象都被析构(一共两次)
}
void playobj() {
g();
}
void playobj2() {
// 用匿名对象初始化m 此时c++编译器直接把匿名对象转为m
Location m = g();
cout << "匿名对象不会被析构" << endl;
cout << m.GetX() << endl;
}
void playobj3() {
// 匿名对象赋值给m2后,匿名对象被析构
Location m2(1, 2);
m2 = g();
cout << "匿名对象赋值给m2 匿名对象被析构" << endl;// 匿名对象赋值给m2 匿名对象被析构
cout << m2.GetX() << endl;
}
void main() {
playobj3();
//playobj2();
//printobj();
}