#include<iostream>
using namespace std;
#include<string>
#include<time.h>
//对象的初始化和清理:利用(由编译器自动调用) 构造函数:创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需动手调用
//析构函数:在于对象销毁前系统的自动调用,执行一些清理工作
//构造函数: 类名(){} //没有返回值也不写void ;!!!!!
//函数名称与类名系统 ;
//构造函数当中可以有参数,因此可以发生重载!
//;程序在调用对象前会自动调用构造,无需手动调用,而且只会调用一次!
//析构函数; ~类名(){} //没有返回值也不写void ;
//函数名称与类名系统 在类名前面加上~ ;
//构造函数当中 不 可以有参数,因此 不 可以发生重载!!!!!
//;程序在调用对象前会自动调用构造,无需手动调用,而且只会调用一次!-----在销毁前调用!!!!!调用一次对象调用一次!!!!!
//class Person
//{
//public://在公共作用域下才能调用!!!!!外边才能访问的到!!!!!
//
// //构造函数 //如果人工不写 编译器也会自动生成一个“Persson(){};”空函数!!!!!会自动调用一次! 如果人工写的话则会调用人工所写的构造函数!!!!!
// Person()
// {
// cout << "Person 构造 函数的调用" << endl;
// }
//
// //析构函数
// ~Person()
// {
// cout << "Person 析构 函数的调用" << endl;
// }
// //构造函数 和 析构函数 都是必须有的实现,如果我们不提供 计算机会自动提供实现一个 空实现 的构造和析构函数!!!!!
//};
//void test01()//在test01里面函数调用完就会 释放存储!!!!!
//{
// Person p;//创建对象,表面上没有调用函数------但是 构造函数会被自动调用 并且只会调用一次!!!!!
// //这是一个局部变量 放在 栈 上的数据,test01执行完毕后会释放这个对象 在释放对象前会自动调用 析构函数!!!!!
//}
//int main()
//{
// test01();//测试函数!
//
// //Person p;//在main()函数里如没有执行完整体运行 函数是 不会被释放的!!!!!!析构函数是释放后才执行的!!!!!
//
// system("pause");
// return 0;
//}
//构造函数的分类与调用:(用途1、给属性初始化)
//分类:1、按参数:有参构造和 无参构造!
//2、按类型:普通构造和 拷贝构造!
//class Person
//{
//public:
// //构造函数
// //按参数分类!
// Person()//()无参数 -即 无参构造(默认构造函数)//如果没有写的话编译器也会提供一个构造函数 即无参构造函数!!!!!
// {
// cout << "Person 的无参 构造函数调用" << endl;
// }
//
// Person(int a)//()有参数 -即 有参构造
// {
// age = a;//下方定义了年龄age对年龄进行赋值操作!
//
// cout << "Person 的有参 构造函数调用" << endl;
// }
//
//
// //!拷贝构造函数!----- 类名(const 类名 &定义变量){} //除这个写法以外的构造都叫 普通构造!!!!1
// Person(const Person &p)//把Person p 里面的所有属性全部拷贝到Person里面来! -----要用 const 固定 并且 用引用的方式 传递!!!!!
// {
// age = p.age;//将传入的变量所有的属性拷贝到当前的对象身上!!!!!(把p的age属性赋值给了Person如今这个对象的age !!!!!
// cout << "Person 的拷贝 构造函数调用" << endl;
// }
//
//
// //析构函数
// ~Person()
// {
// cout << "Person 的析构函数调用" << endl;
// }
//
// int age;
//};
//
//
////调用:括号法、显示法、隐式转换法
//void test01()
//{
////括号法
// //Person c1;//无参(默认)构造函数的调用! //!!!!!!调用一次对象 析构函数就被调用一次!!!!!
// //Person c2(10);//有参函数的调用!
// //Person c3(c2);//拷贝构造函数的调用!
//
// //cout << "c2的年龄为: " << c2.age << endl;
// //cout << "c3的年龄为: " << c3.age << endl;
//
// //注意事项:1:调用无参(默认)函数的时候不要加“()”!!!!!-----如加了()编译器会默认为是 函数的声明!不会认为是创建对象!
//
////显示法
// //Person p1;
// //Person p2 = Person(10);//调用有参构造 //等号右测:!匿名对象! :当前行结束后系统会回收 匿名的对象!!!!!
// //Person p3 = Person(p2);//拷贝构造调用
//
// //注意事项:2:不要利用 拷贝对象 函数来初始化 匿名对象!!!!! 如:Person(p3) 编译器认为其==Person p3; 编译器认为是对象的声明 会使得变量定义重复 !!!!!
//
////隐式转换法
// Person t1 = 10;//相当于:Person t1=Person(10)!!!!!:相当于显示法的调用有参构造!
// Person t2 = t1;//拷贝构造的调用!
//};
//
//
//int main()
//{
// test01();
//
// system("pause");
// return 0;
//}
//拷贝构造函数的调用时机:1、使用一个已经创建完毕的对象初始化一个新对象 2、值传递的方式给函数参数传递值 3、以值的方式返回局部对象
//class Person
//{
//public:
// //无参(默认)构造
// Person()
// {
// cout << "默认 构造函数的调用" << endl;
// }
//
// //有参构造函数
// Person(int age)
// {
// m_age = age;
// cout << "有参 构造函数的调用" << endl;
// }
//
// //拷贝构造函数
// Person(const Person &p)
// {
// m_age = p.m_age;
// cout << "拷贝 构造函数的调用" << endl;
// }
// //析构 函数的调用
// ~Person()
// {
// cout << "析构 构造函数的调用" << endl;
// }
//
// int m_age;
//};
////1、使用一个已经创建完毕的对象初始化一个新对象
//void test01()
//{
// Person p1(20);//括号法调用!!!!!
// Person p2(p1);
//
// cout << "p2的年龄是: " << p2.m_age << endl;
//}
////2、值传递的方式给函数参数传递值
//void doWork1(Person p) //接收到的p和传输到的p不是同一个 p!!!!!!!!!!
//{
//
//}
//void test02()
//{
// Person p;//默认构造函数的调用
// doWork1(p);//相当于实参调用给形参一个拷贝 这个拷贝的构造函数是临时的 会在doWork()内操作!!!!!
//}
////3、以值的方式返回局部对象
//Person doWork2()
//{
// Person c1;
// cout << "C1的地址" << (int *)&c1 << endl;
// return c1;//返回的时候是用值的方式返回 并不是返回c1这个对象 是拷贝出一个新的对象来返回!!!!!
//}
//void test03()
//{
// Person ret = doWork2();
// cout << "ret的地址" << (int *)&ret << endl;
//}
//int main()
//{
// //test01();
// //test02();
// test03();
//
// system("pause");
// return 0;
//}
//在一般情况下写一个类,编译器会给该类添加3个函数:1、默认构造 函数(无参、函数体为 空) //默认构造函数都是要的 !!!!!
//!!!!!! //2、默认析构 函数(无参、函数体为 空)
//3、默认拷贝构造函数,对属性进行值拷贝(会进行一个简单的赋值操作)
//构造函数的调用规则:1、如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造!!!!!
//2、如果用户定义拷贝构造函数,C++不会再提供其他构造函数!!!!!
//class Person
//{
//public:
// Person()
// {
// cout << "Person 的默认构造函数调用" << endl;
// }
//
// Person(int age)
// {
// m_age = age;
// cout << "Person 的有参构造函数调用" << endl;
// }
//
// Person(const Person &p)
// {
// m_age = p.m_age;
// cout << "Person 的拷贝构造函数调用" << endl;
// }
//
// ~Person()
// {
// cout << "Person 的析构函数调用" << endl;
// }
//
// int m_age;
//
//};
//
//void test01()
//{
// Person a;
// a.m_age = 18;
//
// Person b(a);//拷贝 但是就算没在类里面写 拷贝函数 编译器也会自动拷贝一份a当中的值 此行代码依然可以被调用!!!!!
// cout << "b当中的年龄 :" << b.m_age << endl;
//}
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
//深拷贝与 浅拷贝!!!!!
//浅拷贝:编译器提供的简单的赋值拷贝操作!
//深拷贝:在 堆区 重新申请空间进行拷贝操作!
///如果属性内有在堆区开辟的,一定要自己提供拷贝构造函数,防止 浅拷贝带来的问题!!!!!!!!!!
//class Person
//{
//public:
// Person()
// {
// cout << "Person 的 默认构造 函数调用!" << endl;
// }
// Person(int age,int height)
// {
// cout << "Person 的 有参构造 函数调用!" << endl;
// m_age = age;
// m_height=new int(height);//把身高传入堆区! 有int 其返回的是 int* 所以要用指针取接收堆区的数据!
// //堆区数据释放:应该在销毁数据时清除干净 数据在 析构函数调用时销毁!!!!!
// }
//
//
// //自己实现 拷贝构造函数来 解决 浅拷贝 带来的问题-----深拷贝
// Person(const Person &p)
// {
// cout << "拷贝构造函数的调用 " << endl;
// m_age = p.m_age;
// //m_height = p.m_height; 这两行代码是 编译器默认书写的 有问题!!!!!
//
// m_height=new int(*p.m_height);//重新申请一块一样大的内存空间 *p.m_height表示 解引用 把其转变成输入格式!
// }
//
//
// ~Person()//析构函数作用1: 把堆区开辟数据做释放的操作!!!!!!!!!!
// //析构释放原则 先进 后出!!!!!!!!!!
// {
// if (m_height != NULL)//m_height 指针不等于 空
// {
// delete m_height;//清空堆区
// m_height = NULL;//清空 防止野指针出现!!!!!
// }
// cout << "Person 的 析构 函数调用!" << endl;
// }
// int m_age;//年龄
// int *m_height;//指针指向 身高 把身高的数据开辟到堆区!
//};
//void test01()
//{
// Person p1(18,180);
// cout << "P1的年龄是 :" << p1.m_age <<"身高为: "<<*p1.m_height<< endl; //*p2.m_height是为了 解引用 的效果 不然输出的数据是 地址而不是数据!!!!!
//
// Person p2(p1);//拷贝括号法- 编译器提供 的拷贝构造函数提供了 !浅拷贝 操作!类似于对age进行赋值输出!!!!!!!!!!
// cout << "P2的年龄是 :" << p2.m_age << "身高为: " << *p2.m_height << endl;
//
// //p2先被释放出来 后是p1 但是由于 p2把 堆区 释放了,所以p1再次释放会出现错误!!!!!! -浅拷贝 会导致 堆区内存重复释放!!!!!
// //所以应该利用 深 拷贝来解决问题!重新开辟一块堆区 再拷贝一份数据 分别释放空间 -----深拷贝!!!!!
//}
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
//初始化列表!:用来初始化属性 :构造函数():属性1(初值1),属性2(初值2)...{}
//构造函数也能初始化属性 S
//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 p1(10, 20, 30);//创建对象 并且赋值
//
// Person p2(10,20,30);//创建对象同时会自动调用构造函数! 会自动进行赋值操作!
//
// cout << "m_A= :" << p2.m_A << endl;
// cout << "m_B= :" << p2.m_B << endl;
// cout << "m_C= :" << p2.m_C << endl;
//}
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
//类对象作为类成员:C++当中允许一个类当中的对象是另一个类当中的成员(对象成员)
//class A{}
//class B{ A a;} B类当有A作为成员 A为对象成员
//A 类 先 被调用 构造!!!!!B 的 析构 函数 先 被释放!!!!!
//class Phone //手机类
//{
//public:
// //手机品牌
// Phone(string Pname)//设置名称
// {
// m_Pname = Pname;
// cout << "phone的构造函数调用" << endl;
// }
//
// string m_Pname;
//
//};
//class Person //人类
//{
//public:
// Person(string name, string Pname) : m_Name(name), m_Phone(Pname)//构造函数设置并且赋值 触发列表赋值
// //其中有相当于 Phone m_phone=Pname -隐式转换法!
// {
// cout << "person的函数调用" << endl;
// }
//
// //姓名
// string m_Name;
// //手机
// Phone m_Phone;
//};
//void test01()
//{
// Person p("张3", "华为");
// cout << "姓名 : " << p.m_Name << " 手机品牌是 : " << p.m_Phone.m_Pname << endl;
//}
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
//静态成员! 在 成员变量 或 成员函数 前面加上static !
//静态成员分为:(都是有访问权限的!)
//静态成员变量: 1、所有对象共用一份数据 ;2、在编译阶段分配内存 ;3、类内声明,类外初始化(必须要的操作 否则无法访问内存)!!!!!
//静态成员函数:/1、所有对象共享一个函数 ;2、静态成员函数 只能 访问静态成员变量!!!!!
//静态成员变量
//class Person
//{
//public:
// //类内声明!!!!!
// int m_A;//非 静态成员变量
// static int m_B;//静态成员变量
//
////静态成员变量的访问权限!!!!!-----私有权限类外是访问不到的!!!!!
//private:
// static int m_C;
//
//};
////类外初始化
////int Person::m_A=200;-----只有静态变量才能类外初始化!!!!!
// int Person:: m_B=100;//-----静态变量类外初始化!
//
// int Person::m_C = 300;
//
//void test01()
//{
// Person p;
// //cout << p.m_A << endl;
// cout << p.m_B << endl; //100
//
// Person p2;
// p.m_B = 300;
// cout << p2.m_B << endl; //300 -----关系的是一块数据
//
//}
//
////静态成员变量不属于某个对象上,所有对象都共享同一分数据
//void test02()
//{
// //静态成员变量有2种访问方式
// //1、通过对象进行访问
// //Person p;
// //cout << p.m_B << endl; //100-初始化时作用是100
// //2、通过类名直接访问
// cout << Person::m_B << endl; //直接 显示Person作用域下的m_B -----通过类名的方式访问静态成员变量!!!!!
//}
//int main()
//{
// //test01();
// test02();
// system("pause");
// return 0;
//}
//静态成员函数
class Person
{
public:
void func03()//普通的成员函数
{
}
static void func()//静态的成员函数!
{
m_A = 90000; //静态成员函数是 可以访问 静态成员变量的!!!!!
//m_B = 100;//!报错! - //静态成员函数是 不能访问 非 静态成员变量!!!!!-会无法区分是那份数据
cout << "static void func()的调用" << endl;
}
static int m_A; //静态成员变量
int m_B; //非静态成员变量
};
int Person::m_A = 100;
void test01()
{
//通过 对象 访问静态成员函数!
Person p;
p.func(); //调用对象函数时记得加()!!!!!
//通过 类名 访问静态成员函数!
Person::func();
}
int main()
{
test01();
system("pause");
return 0;
}