目录
默认构造函数
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
//构造函数(构造器), 是为了给对象提供初始化而出现的。
//函数名字跟类型是一样的,没有返回值,并且可以重载
//无参数的构造函数
Test()
{
m_x = 0;
m_y = 0;
p = (char*)malloc(100);
strcpy(p, "123");
}
//带参数的构造函数
Test(int x, int y)
{
m_x = x;
m_y = y;
}
//一个参数的构造函数
Test(int x)
{
m_x = x;
m_y = 0;
}
//析构函数 : ~+类型 没有任何的参数
~Test()
{
cout << "Test 的析构函数~Test() 被调用了" << endl;
if (p != NULL) {
cout << "p的堆空间被释放了" << endl;
free(p);
p = NULL;
}
}
void printT()
{
cout << "x : " << m_x << ", y: " << m_y << endl;
}
void init(int x, int y)
{
m_x = x;
m_y = y;
}
private:
int m_x;
int m_y;
char *p;
};
//给对象搭建一个舞台,研究对象的行为
void test1()
{
Test t1; //调用无参数的构造函数
//t1 是一个局部变量, 生命周期是test1()一样的, 在test1()函数执行完毕需要 先销毁t1变量
//t1对象销毁之前,系统就会默认的调用t1的析构函数
t1.printT();
return;
}
int main(void)
{
Test t1; //t1 在开辟内存之后,t1中的m_x m_y 是随机值
t1.init(10, 20); //每次都需要显示的调用一个初始化的函数。
//能不能提供一个 在创建一个对象的时候就给他初始化呢?
// test1();
//Test t1; //创建一个对象, 这个对象会直接调用无参数的构造函数。
//Test t2(10, 20); //在创建对象完毕之后, 就已经将对象的一些成员变量初始化了
//Test t3(10);
return 0;
}
构造函数与析构函数
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
//默认构造函数。 就是一个无参数的构造函数,
//如果不显示提供构造函数,系统就是调用默认的构造函数
/*
Test() {} 默认的构造函数,已经手动提供,默认就被隐藏
*/
//如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。
//构造函数一旦手动提供, 默认将不复存在。
Test(int x, int y)
{
m_x = x;
m_y = y;
cout << "调用了有参数的构造函数" << endl;
}
//无参数的构造函数
Test(){
m_x = 0;
m_y = 0;
cout << "调用了无参数的构造函数" << endl;
}
//拷贝构造函数 ,想通过另一个Test对象 another 将本对象进行拷贝
Test(const Test & another)
{
m_x = another.m_x;
m_y = another.m_y;
cout << "调用了拷贝构造函数" << endl;
}
//等号操作符
void operator = (const Test &t)
{
m_x = t.m_x;
m_y = t.m_y;
}
void printT()
{
cout << "x : " << m_x << ", y : " << m_y << endl;
}
//提供一个析构函数
~Test()
{
cout << "~Test()析构函数被执行了" << endl;
cout << "(" << m_x << ", " << m_y << ")" << "被析构了" << endl;
}
private:
int m_x;
int m_y;
};
int main(void)
{
Test t1; //调用无参的构造函数
Test t2(10, 20);
//Test t3(10, 20, 30);
t2.printT();
Test t3(t2); //调用t3的拷贝构造函数 //调用拷贝构造函数的方式
t3.printT();
//Test t4 = t2; // 依然是调用t4的拷贝构造函数,
Test t4(100, 200); //调用t4 的两个参数的构造函数
Test t5; //先调用无惨构造。
t5 = t2; //不会调用拷贝构造函数 //调用=号重载操作符 赋值操作符
//析构函数的调用顺序, 跟对象的构造顺序相反, 谁先构造,谁最后一个被析构。
return 0;
}
构造函数的三种调用方法
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
//默认构造函数。 就是一个无参数的构造函数,
//如果不显示提供构造函数,系统就是调用默认的构造函数
/*
Test() {} 默认的构造函数,已经手动提供,默认就被隐藏
*/
int value = 100;
//如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。
//构造函数一旦手动提供, 默认将不复存在。
Test(int x, int y)
{
m_x = x;
m_y = y;
cout << "调用了有参数的构造函数" << endl;
}
//无参数的构造函数
Test(){
m_x = 0;
m_y = 0;
cout << "调用了无参数的构造函数" << endl;
}
//拷贝构造函数 ,想通过另一个Test对象 another 将本对象进行拷贝
Test(const Test & another)
{
m_x = another.m_x;
m_y = another.m_y;
cout << "调用了拷贝构造函数" << endl;
}
//等号操作符
void operator = (const Test &t)
{
m_x = t.m_x;
m_y = t.m_y;
}
void printT()
{
cout << "x : " << m_x << ", y : " << m_y << endl;
}
//提供一个析构函数
~Test()
{
cout << "~Test()析构函数被执行了" << endl;
cout << "(" << m_x << ", " << m_y << ")" << "被析构了" << endl;
}
private:
int m_x;
int m_y;
};
int main(void)
{
//Test t15();
//cout << t15.value << endl; //error写了(),就要有参数
Test t1; //调用无参的构造函数
Test t2(10, 20);
//Test t3(10, 20, 30);
t2.printT();
Test t3(t2); //调用t3的拷贝构造函数 //调用拷贝构造函数的方式
t3.printT();
//Test t4 = t2; // 依然是调用t4的拷贝构造函数,
Test t4(100, 200); //调用t4 的两个参数的构造函数
Test t5; //先调用无参构造。
t5 = t2; //不会调用拷贝构造函数 //调用=号重载操作符 赋值操作符
//析构函数的调用顺序, 跟对象的构造顺序相反, 谁先构造,谁最后一个被析构。
return 0;
}
为什么需要构造和析构函数
copy构造函数的调用时机
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
//默认构造函数。 就是一个无参数的构造函数,
//如果不显示提供构造函数,系统就是调用默认的构造函数
/*
Test() {} 默认的构造函数,已经手动提供,默认就被隐藏
*/
//如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。
//构造函数一旦手动提供, 默认将不复存在。
Test(int x, int y)
{
m_x = x;
m_y = y;
cout << "调用了有参数的构造函数" << endl;
}
//无参数的构造函数
Test(){
m_x = 0;
m_y = 0;
cout << "调用了无参数的构造函数" << endl;
}
//拷贝构造函数 ,想通过另一个Test对象 another 将本对象进行拷贝
Test(const Test & another)
{
m_x = another.m_x;
m_y = another.m_y;
cout << "调用了拷贝构造函数" << endl;
}
//等号操作符
void operator = (const Test &t)
{
cout << "调用了=号操作符" << endl;
m_x = t.m_x;
m_y = t.m_y;
}
void printT()
{
cout << "x : " << m_x << ", y : " << m_y << endl;
}
//提供一个析构函数
~Test()
{
cout << "~Test()析构函数被执行了" << endl;
cout << "(" << m_x << ", " << m_y << ")" << "被析构了" << endl;
}
private:
int m_x;
int m_y;
};
//拷贝构造函数的第一个场景
void test1()
{
Test t1(1, 2);
Test t2(t1);
//通过t1 给t2 进行赋值
t2.printT();
}
//拷贝构造函数的第二场景
void test2()
{
Test t1(1, 2);
Test t2;
t2 = t1; //调用的不是拷贝构造函数,调用的是 =号操作符,也能够完成将t1的值给t2 但不是调用t2的拷贝构造函数。
}
void func(Test t) //Test t = test1::t1; //会调用局部变量t的拷贝构造函数
{
cout << "func begin..." << endl;
t.printT();
cout << "func end..." << endl;
}
//场景三
void test3()
{
cout << "test3 begin ..." << endl;
Test t1(10, 20); //创建了一个t1的对象。通过t1的有参数的构造函数
func(t1);
cout << "test3 end..." << endl;
}
int func(void)
{
int a = 10;
return a;
}
//场景四
Test func2()
{
cout << "func2 begin..." << endl;
Test temp(10, 20); //调用temp的带参数构造函数
cout << "func2 end.." << endl;
return temp; // 有一个临时的匿名对象 = temp ,把temp的数据给到了临时的匿名对象, ,会调用这个临时匿名
//对象的拷贝构造函数, 将temp穿进去。
}
void test4()
{
cout << "test4 begin " << endl;
func2();
//匿名对象在此被析构了, 如果一个临时的匿名对象,没有任何变量去接收它,编译器认为这个临时匿名对象没有用处。
//编译器会立刻销毁这个临时的匿名对象
cout << "test4 end" << endl;
}
void test5()
{
cout << "test5 begin ..." << endl;
Test t1 = func2();//如果有一个变量去接收这个临时的匿名对象, 编译器认为这个匿名对象转正了,就不会立刻给他销毁。
//t1 = 匿名的临时对象 为什么不会发生拷贝构造
// 此时的t1 去接收这个匿名的临时对象不是 重新创建一个t1 而是给这个匿名对象起个名字就叫t1
//一旦这个匿名对象有了自己的名字,编译器就不会立刻给这个匿名对象销毁了,
//就当普通局部变量处理了
cout << "test5 end..." << endl;
//在此时析构的t1
}
void test6()
{
cout << "test6 begin..." << endl;
Test t1; //调用t1的无参数构造函数
t1 = func2(); //调用的=号操作符 ,,t1 = 匿名对象。 调用了t1的=号操作符。
//此时匿名没有被转正,匿名没有自己的名字, 匿名对象这个内存没有自己的别名, 编译器就会立刻销毁。
cout << "test6 end..." << endl;
}
int main(void)
{
//test3();
//test4();
//func();
//test5();
test6();
return 0;
}
匿名对象的去和留
默认构造和默认拷贝构造
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class B
{
public:
/*
默认提供的函数
B() {
//默认的无惨构造函数
}
B(const B& b)
{
m_b = b.m_b; //默认的拷贝构造函数
p = b.p;
}
~B()
{
//默认的析构函数
}
*/
//如果显示的写了一个普通构造函数, 会隐藏默认的无惨构造函数
//如果显示的写了一个拷贝构造函数 ,会隐藏默认的无参构造函数和默认的拷贝构造函数
//如果显示的写了一个析构函数, 会隐藏默认的析构函数
B(const B& b)
{
}
private:
int m_b;
char *p;
};
class A
{
public:
/*
默认的构造函数
如果普通构造函数,提供了一个显示的构造, 那么这个无参的默认构造就会被隐藏。 不会把拷贝构造函数隐藏掉
A()
{
}
*/
A(int a)
{
m_a = a;
}
/*
默认的拷贝构造函数
A(const A & a)
{
m_a = a;
}
*/
//显示的提供一个拷贝构造的函数的时候,默认的拷贝构造函数就会被隐藏
A(const A &a) {
cout << "显示提供的拷贝构造函数" << endl;
m_a = a.m_a;
}
/*
默认的析构函数
~A()
{
}
*/
//只有提供一个显示的析构函数,才会将默认的析构覆盖点
~A()
{
cout << "A的析构函数 调用 " << endl;
}
private:
int m_a;
};
int main(void)
{
A aObj(10); //当你不提供任何构造函数的时候, 系统会有一个默认的构造函数
A aObj2 = aObj; //调用了aObj2的拷贝构造函数
//A aObj2(aObj);
return 0;
}
拷贝构造函数作用用一个对象初始化另一个对象
构造函数的调用规则研究