目录
一、this指针
二、构造系列
1.对象的种类
2.构造函数
3.析构函数
4.实现一个date类 (万年历)练习
5.拷贝构造
6.浅拷贝与深拷贝问题
三、static与const
1.static成员
2.const
一、this指针
空类的对象占一个字节
类中的成员变量 创建对象时才存在 每个对象都有自己独立的一份
类中的成员函数 编译期存在 只有一份
this指针 关键字 指向当前调用本成员函数的对象
this指针只能在成员函数(非静态)中使用
#includeusing namespace std; class AA { public: int a; char b; public: void Show(int a) { cout << "AA" << endl; cout << this->a << " " << this->b << endl; this->a = a; //this++; } }; class BB { public: void Show() { cout << "BB" << endl; } }; int main() { AA a; cout << sizeof(a) << endl; cout << sizeof(BB) << endl; system("pause"); return 0; }
输出:
8 1 请按任意键继续. . .
二、构造系列
1.对象的种类
#includeusing namespace std; class AA { public: AA() { cout << "AA" << endl; } ~AA() { cout << "~AA" << endl; } }; //AA a; //全局大括号之后回收 int main() { //AA a; //局部对象 栈区 return之后 大括号之前 //堆区对象 //临时对象 cout << "---------" << endl; AA(); cout << "---------" << endl; system("pause"); return 0; }
输出:
--------- AA ~AA --------- 请按任意键继续. . .
2.构造函数
构造函数 ,是一种特殊的方法。. 主要用来在创建对象时初始化对象, 即为对象 成员变量 赋初始值,总与new 运算符 一起使用在创建对象的语句中。. 特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的 重载 。
#includeusing namespace std; class Student { public: const char* m_Name; int m_Age; public: Student() { m_Name = "小明"; m_Age = 18; } Student(const char* str) { m_Name = str; m_Age = 17; } Student(const char* str, int age) { m_Name = str; m_Age = 18; } }; int main() { Student stu; cout << stu.m_Name << " " << stu.m_Age << endl; Student stu1("小强"); cout << stu1.m_Name << " " << stu1.m_Age << endl; Student* pStu = new Student("小芳",18); cout << pStu->m_Name << " " << pStu->m_Age << endl; Student* pStu1 = (Student*)malloc(sizeof(Student)); system("pause"); return 0; }
输出:
小明 18 小强 17 小芳 18 请按任意键继续. . .
3.析构函数
析构函数与构造函数相反,当对象结束其 生命周期 ,如对象所在的 函数 已 调用 完毕时,系统自动执行析构函数。. 析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放 内存 )。
#includeusing namespace std; #include class Phone { public: string m_PhoneName; public: Phone(string name) { m_PhoneName = name; cout << "Phone的构造" << endl; } ~Phone() { cout << "Phone的析构" << endl; } }; class Person { public: string m_name; Phone m_Phone; public: Person(string name,string pName):m_name(name),m_Phone(pName) { cout << "Person的构造" << endl; } ~Person() { cout << "Person的析构" << endl; } public: void Print(); }; void Person::Print() { cout << m_name << "使用" << m_Phone.m_PhoneName << "的手机" << endl; } void test() { Person p("小明", "苹果MAX"); p.Print(); } int main() { test(); system("pause"); return 0; }
输出:
Phone的构造 Person的构造 小明使用苹果MAX的手机 Person的析构 Phone的析构 请按任意键继续. . .
4.实现一个date类 (万年历)练习
//三个私有的成员变量 年 月 日
//默认出厂日期为1900-1-1
//显示当前日期
//设置日期(校验日期合法性)
//附加一个初始化函数
#includeusing namespace std; class Date { private: int m_Year; int m_Month; int m_Day; public: Date(); Date(int year, int month, int day); public: void SetYear(int year); void SetMonth(int month); void SetDay(int day); void Show(); void InitDate(int year, int month, int day); }; Date::Date() { m_Year = 1900; m_Month = 1; m_Day = 1; } void Date::SetYear(int year) { m_Year = year; } void Date::SetMonth(int month) { if (month >= 1 && month <= 12) { m_Month = month; } else { cout << "月份违法" << endl; } } void Date::SetDay(int day) { if (day >= 1 && day <= 30) { m_Day = day; } else { cout << "日期违法" << endl; } } void Date::Show() { cout << m_Year << "-" << m_Month << "-" << m_Day << endl; } Date::Date(int year, int month, int day) :m_Year(year), m_Month(month), m_Day(day) { } void Date::InitDate(int year, int month, int day) { m_Year = year; m_Month = month; m_Day = day; } int main() { Date d; d.Show(); d.SetYear(2022); d.SetMonth(6); d.SetDay(13); d.Show(); Date d1(2022, 6, 13); d1.Show(); Date dd[5]; for (int i = 0; i < 5; i++) { dd[i].InitDate(2022, 6, 13); } for (int i = 0; i < 5; i++) { dd[i].Show(); } system("pause"); return 0; }
输出:
1900-1-1 2022-6-13 2022-6-13 2022-6-13 2022-6-13 2022-6-13 2022-6-13 2022-6-13 请按任意键继续. . .
5.拷贝构造
拷贝构造函数的参数可以是 const 引用,也可以是非 const 引用。 一般使用前者,这样既能以常量对象(初始化后值不能改变的对象)作为参数,也能以非常量对象作为参数去初始化其他对象。一个类中写两个拷贝构造函数,一个的参数是 const 引用,另一个的参数是非 const 引用,也是可以的。
如果类的设计者不写拷贝构造函数,编译器就会自动生成拷贝构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认拷贝构造函数”。
注意,默认构造函数(即无参构造函数)不一定存在,但是拷贝构造函数总是会存在。
不能在类中定义本类的对象
类中含有一个默认的拷贝构造函数 只有一个参数是本类类型的引用的构造函数
什么情况下会调用拷贝构造
1.用一个对象初始化另一个对象时
2.类对象作为函数参数时
3.函数返回值为类对象时 原因:用局部对象初始化临时对象
#includeusing namespace std; class Student { public: const char* m_Name; int m_Age; public: Student() { } Student(const char* name,int age) { m_Name = name; m_Age = age; } Student(Student& a) { m_Name = a.m_Name; m_Age = a.m_Age; cout << "COPY" << endl; } public: void Show() { cout << m_Name << " " << m_Age << endl; } }; void Show(Student& stu) { cout << stu.m_Name << " " << stu.m_Age << endl; } //Student Fun() int main() { Student stu1("小明",17); stu1.Show(); // Student stu2 = stu1; stu2.Show(); Student stu3(stu1); stu3.Show(); Student stu4; stu4 = stu1; stu4.Show(); // //Show(stu1); //Fun(); system("pause"); return 0; }
输出:
小明 17 COPY 小明 17 COPY 小明 17 小明 17 请按任意键继续. . .
6.浅拷贝与深拷贝问题
浅拷贝 将源对象的值拷贝到目标对象
深拷贝 拷贝的时候先开辟一个与源对象成员空间大小一样的空间 然后再将空间中的内容赋值过来
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。所以在delete时浅拷贝容易造成二次释放的问题,所以我们拷贝构造函数一定要深拷贝。
代码如下:
#includeusing namespace std; //浅拷贝 将源对象的值拷贝到目标对象 //深拷贝 拷贝的时候先开辟一个与源对象成员空间大小一样的空间 然后再将空间中的内容赋值过来 class AA { public: int* p; public: AA() { p = new int; *p = 100; } ~AA() { delete p; } public: AA(AA &a) { p = new int; *p = *a.p; } }; void Show(AA& a) //用类的引用作为函数参数 { cout << *a.p << endl; } int main() { AA a; cout <<* a.p << endl; AA b = a; cout <<* b.p << endl; Show(a); system("pause"); return 0; }
输出:
100 100 100 请按任意键继续. . .
三、static与const
1.static成员
全局变量 使用范围整个程序 在其他文件中使用要外部引用 extern
静态变量 适用范围 在作用域定义 本作用域内 在作用域外定义 当前文件
静态成员变量 只有一份 所有对象共享
静态成员在类外初始化
初始化格式: 类型 + 类名::+ 变量名
静态成员变量必须要在类外初始化 如果不赋值默认初始化为0
可以不用对象直接访问 类名::+变量名
依旧遵循访问修饰符的约束
普通成员函数可以使用静态成员变量
静态成员函数只能使用静态成员变量 不能使用普通成员变量
静态成员函数没有this指针
#includeusing namespace std; class AA { public: static int a; int b; public: void Show() { cout << a << " " << b << endl; } static void ShowShow(); }; int AA::a ; void AA::ShowShow() { cout << a << " " << endl; } int main() { cout << AA::a << endl; //AA a; a.a = 100; //a.b = 200; //a.Show(); //AA b; //b.a = 1000; //b.b = 20; //b.Show(); //cout << sizeof(AA) << endl; system("pause"); return 0; }
2.const
类中包含const成员变量 要在初始化列表中初始化
在类成员函数的后面加一个const 表示该函数为常函数
const放在函数返回值前 表示函数返回值是一个常量
常函数限制了this指针 不能通过this指针去修改当前对象中的成员变量
常对象只能调用常函数
#includeusing namespace std; class AA { public: const int a; int b; public: AA() :a(100) { b = 200; } public: void Show() { cout << a << endl; this->b = 300; cout << b << endl; } void ShowShow() const; }; void AA::ShowShow() const { cout << a << endl; //this->b = 300; cout << b << endl; } int main() { AA a; a.Show(); a.ShowShow(); const AA b; b.ShowShow(); system("pause"); return 0; }



