1、构造函数和析构函数
#include<iostream>
using namespace std;
//1、构造函数 进行初始化操作
class person
{
//1、构造函数
//没有返回值,不用写void
/*函数名和类名相同
构造函数可以有参数,可以发生函数重载
创建对象时,构造函数会自动调用,而且只会调用一次*/
public:
person()
{
cout << "函数的调用" << endl;
}
//2、析构函数
//没有返回值,不用写void
//函数名和类名相同 在名称前加 ~
//构造函数不可以有参数,不可以发生函数重载
//对象在销毁前,会自动调用析构函数,而且只会调用一次
~person()
{
cout << "析构函数函数的调用" << endl;
}
};
//构造函数和析构函数都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现的构造和析构
void test01()
{
person p;//栈区 上的数据,test01执行完毕后,释放这个对象
}
int main()
{
test01();
system("pause");
return 0;
}
2、构造函数的分类与调用
#include<iostream>
using namespace std;
//1、分类
// 按照有无参数分类 无参构造(默认构造)和 有参构造
// 按照类型分类 普通构造 拷贝构造
class person
{
public:
person()
{
cout << "无参构造函数的调用" << endl;
}
person(int a)
{
age = a;
cout << "有参构造函数的调用" << endl;
}
//拷贝构造函数
person(const person& p)
{
//将传入的人身上所有属性,拷贝到我身上
age = p.age;
cout << "拷贝构造函数的调用" << endl;
}
~person()
{
cout << "析构函数的调用" << endl;
}
int age;
};
//调用
void test02()
{
//1.括号法
//person p1;//默认构造函数
//person p2(10);//有参构造函数
//person p3(p1);//拷贝构造函数
//注意事项
//调用默认构造函数时不要加()
//因为下面这行代码,编译器会认为是一个函数的声明,不会认为在创建对象
//person p();
//2.显示法
person p1;
person p2 = person(10);//有参构造
person p3 = person(p2);//拷贝构造
//注意事项2.1:person(10);//匿名函数 特点:当前行执行结束后,系统会立即回收匿名对象
//cout << "aaa" << endl;
//2.2不要利用拷贝构造函数 初始化匿名对象 编译器会认为 person(p3) == person p3;即对象的声明
//person(p3);
/*cout << "p2的年龄:" << p2.age << endl;
cout << "p3的年龄:" << p3.age << endl;*/
//3.隐式转换法
person p4 = 10;//相当于写了 person p4 = person(10);即有参构造函数
person p5 = p4;
}
int main()
{
test02();
return 0;
}
3、拷贝构造函数的调用时机
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout << "无参构造函数的调用" << endl;
}
person(int a)
{
age = a;
cout << "有参构造函数的调用" << endl;
}
person(const person& p)
{
age = p.age;
cout << "拷贝构造函数的调用" << endl;
}
~person()
{
cout << "析构构造函数的调用" << endl;
}
int age;
};
//1.使用一个已经创建完毕的对象来初始化一个新对象
void test03()
{
person p1(10);
person p2(p1);
}
//2.值传递的方式给函数参数传值
void dowork(person pp)//值传递 相当于隐式转换法 person pp = p3;
{
}
void test04()
{
person p3;
dowork(p3);//相当于隐式转换法 person pp = p3;
}
//3.值方式返回局部对象
person dowork2()
{
person p6;
cout << &p6 << endl;
return p6;//局部变量在函数执行完后会自动释放,因此需要要一个变量来接受p6,即从test05;
}
void test05()
{
person p = dowork2();//隐式转换法
cout << &p << endl;
}
int main()
{
test05();
return 0;
}
4、构造函数的调用规则
#include<iostream>
using namespace std;
//构造函数的调用规则
//1、创建一个类,c++编译器会给每个类都添加至少3个函数
//默认构造函数(空实现)
//析构函数(空实现)
//拷贝构造(值拷贝) //注释原有的拷贝函数实现后即23行到27行,值依然可以复制到拷贝函数
//2、如果我们写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造
//3、如果我们写了拷贝构造函数,编译器就不再提供其他构造函数
class person
{
public:
//person()
//{
// cout << "无参构造函数的调用" << endl;
//}
//person(int a)
//{
// age = a;
// cout << "有参构造函数的调用" << endl;
//}
person(const person& p)
{
age = p.age;
cout << "拷贝构造函数的调用" << endl;
}
~person()
{
cout << "析构构造函数的调用" << endl;
}
int age;
};
//void test001()
//{
// person p1;
// p1.age = 18;
// person p2(p1);
//
// cout << p2.age << endl;
//}
//void test002()
//{
// person p1(28);
// person p2(p1);
// cout << p2.age << endl;
//}
void test003()
{
person p1 = person(p1);
}
int main()
{
//test001();
//test002();
test003();
return 0;
}
5、浅拷贝和深拷贝
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout << "无参构造函数的调用" << endl;
}
person(int a,int hight)
{
age = a;
m_hight = new int(hight);
cout << "有参构造函数的调用" << endl;
}
person(const person& p)
{
cout << "拷贝构造函数的调用" << endl;
age = p.age;
//m_hight = p.m_hight;//浅拷贝的就是编译器默认实现这行代码
//深拷贝操作
m_hight = new int(*p.m_hight);
}
~person()
{
//析构代码,将堆区开辟数据作释放的操作
if (m_hight != NULL)
{
delete m_hight;
m_hight = NULL;
}
cout << "析构构造函数的调用" << endl;
}
int age;
int* m_hight;
};
void test01()
{
person p1(18, 160);
cout << p1.age << *p1.m_hight << endl;
person p2(p1);
cout << p2.age << *p2.m_hight << endl;
}
int main()
{
test01();
return 0;
}
6、初始化列表初始化值
#include<iostream>
using namespace std;
class person
{
public:
//传统初始化操作
//person(int a,int b,int c)
//{
// m_a = a;
// m_b = b;
// m_c = c;
//}
//初始化列表初始化属性
person(int a,int b,int c) :m_a(a), m_b(b), m_c(c)
{
}
int m_a;
int m_b;
int m_c;
};
void test01()
{
person p(30,20,10);
cout << p.m_a << endl;
cout << p.m_b << endl;
cout << p.m_c << endl;
}
int main()
{
test01();
return 0;
}
7、类对象作为类成员
#include<iostream>
using namespace std;
class phone
{
public:
phone(string pname)
{
cout << "phone" << endl;
m_pname = pname;
}
~phone()
{
cout << "phone析构构造函数的调用" << endl;
}
string m_pname;
};
class person
{
public:
person(string name, string pname) :m_name(name), m_phone(pname)
{
cout << "person" << endl;
}
~person()
{
cout << "person析构构造函数的调用" << endl;
}
string m_pname;
string m_name;
phone m_phone;
};
//当其他类对象作为本类成员,构造时候先构造其他类对象,再构造本身;析构的顺序与构造相反
void test()
{
person p("张三", "华为");
cout << p.m_name << "拿着" << p.m_phone.m_pname << endl;
}
int main()
{
test();
return 0;
}
8、静态成员变量
#include<iostream>
using namespace std;
class person
{
//静态成员变量
public:
//1、所有对象都共享一份数据
//2、在编译阶段分配内存
//3、类内声明,类外初始化操作
static int m_a;
//静态成员变量也是有访问权限的
private:
static int m_b;
};
int person::m_a = 100;//3.2类外初始化操作
int person::m_b = 200;
void test()
{
person p;
cout << p.m_a << endl;
person p2;
p2.m_a = 200;
cout << p.m_a << endl; //1、所有对象都共享一份数据;所以用p去访问时为200
}
void test02()
{
//静态成员变量 不属于某个对象上,所有对象都共享同一份数据
//因此静态成员变量有两种访问方式
//1、通过对象进行访问
//person p;
//cout << p.m_a << endl;
//2、通过类名进行访问
cout << person::m_a << endl;
//cout << person::m_b << endl;//静态成员变量也是有访问权限的
}
int main()
{
//test();
test02();
return 0;
}
9、静态成员函数
#include<iostream>
using namespace std;
class person
{
public:
//静态成员函数
//1.所有对象共享同一个函数
//2.静态成员函数只能访问静态成员变量
static void func()
{
cout << "static void func的调用" << endl;
m_a = 200; //静态成员函数可以访问静态成员变量
//m_b = 300;//静态成员函数不可以访问非静态成员变量,因为非静态成员变量是某个对象有的,所以无法区分到底是哪个对象的
}
//静态成员变量
static int m_a;//记得类内声明,类外初始化
int m_b;//非静态成员变量
//静态成员函数也是有访问权限的
private:
static void func02()
{
cout << "static void func02的调用" << endl;
}
};
int person::m_a = 100;
void test()
{
//两种访问方式
//1、通过对象访问
person p;
p.func();
//2、通过类名访问 //所有对象共享同一个函数
person::func();
//person::func02(); 静态成员函数也是有访问权限的
}
int main()
{
test();
return 0;
}
|