C++类和对象1:https://developer.aliyun.com/article/1548154
4、构造函数调用规则
默认情况下,C++编译器至少给一个类添加3个函数
a、默认构造函数(无参、函数体为空);b、默认析构函数(无参、函数体为空);c、默认拷贝构造函数,对属性进行值拷贝;d、如果用户定义了有参构造函数,编译器会提供拷贝构造函数,不会提供无参构造函数;如果用户定义了拷贝构造函数,编译器不会提供无参构造函数。
#include <iostream> using namespace std; //构造函数的调用规则 //1、创建一个类,C++编译器会给每个类都添加至少3个函数; //默认构造 (空实现) //析构函数 (空实现) //拷贝构造 (值拷贝) class Person { public: Person() { cout << "默认构造函数" << endl; } Person(int age) { cout << "有参构造函数" << endl; m_Age = age; } // // Person(const Person &p) { // m_Age = p.m_Age; // cout << "拷贝构造函数" << endl; // } ~Person() { cout << "析构函数" << endl; } int m_Age; }; void test01() { Person p; p.m_Age = 18; Person p2(p); cout << "p2的年龄为:" << p2.m_Age << endl; } int main() { test01(); return 0; }
默认构造函数 p2的年龄为:18 析构函数 析构函数
5、深拷贝与浅拷贝
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝,堆区的内存重复释放
#include <iostream> using namespace std; //深拷贝与浅拷贝 class Person { public: Person() { cout << "Person的默认构造函数调用" << endl; } Person(int age, int hegith) { m_Age = age; m_Height = new int(hegith);//堆区 cout << "Person的有参构造函数调用;" << endl; } Person(const Person &p) { cout << "执行拷贝构造函数" << endl; m_Age = p.m_Age; // 执行深拷贝 浅拷贝代码:m_Height =p.m_Height m_Height = new int(*p.m_Height); } ~Person() { // 析构代码,将堆区开辟数据做释放操作 if (m_Height != NULL) { // 浅拷贝,堆区的内存重复释放 delete m_Height; // 避免野指针出现 m_Height = NULL; } cout << "析构函数" << endl; } int m_Age;//年龄 int *m_Height;//身高 }; void test01() { Person p1(18, 160); cout << "p1的年龄为:" << p1.m_Age << " " << *p1.m_Height << endl; Person p2(p1); cout << "p2的年龄为:" << p2.m_Age << " " << *p2.m_Height << endl; } int main() { test01(); return 0; }
6 、初始化列表
作用:C++提供了初始化列表语法,用来初始化属性;
#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 p1(1, 2, 3); Person p1(1,2,3); cout << p1.m_A << p1.m_B << p1.m_C << endl; } int main() { // 初始化列表 test01(); return 0; }
7、类对象作为类成员
当类中成员是其他类对象时,我们称该成员为对象成员,
构造顺序:先调用对象成员的构造,再调用本类构造,析构顺序相反.
#include <iostream> using namespace std; class Phone { public: Phone() { cout << "Phone 的构造函数" << endl; } Phone(string name) : p_name(name) { cout << "Phone 有参的构造函数" << endl; } ~Phone() { cout << "Phone 的析构函数" << endl; }; string p_name; }; class Person { public: Person() { cout << "Person 的构造函数" << endl; } Person(string name, string pName) : name(name), phone(pName) { cout << "Person 的有参构造函数" << endl; } ~Person() { cout << "Person 的析构函数" << endl; }; string name; // 对象成员 Phone phone; }; //当类中成员是其他类对象时,我们称该成员为对象成员,构造顺序:先调用对象成员的构造,再调用本类构造,析构顺序相反. void test() { Person person("zhangsan","sanxing"); cout<<person.phone.p_name<<endl; } int main() { // 初始化列表 test(); return 0; }
Phone 有参的构造函数 Person 的有参构造函数 sanxing Person 的析构函数 Phone 的析构函数
8 、静态成员
静态成员就是在成员变量和成员函数前加上关键字static,成为静态成员。
静态成员变量:所有对象共享同一份数据,在编译阶段分配内存,类内申明,类外初始化;
静态成员函数:所有对象共享同一个函数,静态成员函数只能访问静态成员变量。
#include <iostream> using namespace std; //静态成员就是在成员变量和成员函数前加上关键字static,成为静态成员。 //静态成员变量 class Person { public: //静态成员变量:所有对象共享同一份数据,在编译阶段分配内存,类内申明,类外初始化; static int m_A; int m_B; //静态成员函数:所有对象共享同一个函数,静态成员函数只能访问静态成员变量。 static void func() { cout << "static void func调用" << endl; // 静态成员函数只能访问静态成员变量 cout << m_A << endl; } }; int Person::m_A = 100; void test() { Person p; cout << p.m_A << endl; Person p2; p2.m_A = 200; cout << p.m_A << endl; } //静态成员变量 void test02() { Person p1; // 1、通过对象进行访问 cout << p1.m_A << endl; // 2、通过类访问 cout << Person::m_A << endl; } void test03(){ Person::func(); } int main() { // test(); // test02(); test03(); return 0; }
static void func调用 100
三、对象模型和this指针
1、成员变量与成员函数分开存储
空对象占用1个字节空间,非静态成员属于类的对象。
#include <iostream> using namespace std; //成员变量和成员函数分开存储 class Person { public: int m_A; //非静态成员变量,属于类的对象 static int m_B; //静态成员变量,不属于类的对象 void func() {};//非静态成员函数,不属于类的对象 static void funcs() {}; //静态成员函数,不属于类的对象 }; int Person::m_B = 100; void test01() { Person p; //空对象占用内存空间为:1 //C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置 // 每个空对象都有独一无二的内存地址 cout << "size of p=" << sizeof(p) << endl; } void test02() { Person p; cout << "size of p=" << sizeof(p) << endl; } int main() { // test01(); test02(); return 0; }
size of p=4
2、this指针概念
this指针指向被调用的成员函数所属的对象。
this指针是隐含每一个非静态成员函数内的一种指针;
this指针不需要定义,直接使用即可;
用途:
当形参和成员变量同名时,可用this指针来区分;
在类的非静态成员函数中返回对象本身,可使用return *this;
#include <iostream> using namespace std; class Person { public: // Person(int age) : age(age) {}; Person(int age) { // this指针指向被调用的成员函数所属的对象。 this->age = age; } Person &PersonAddAge(Person &p) { this->age += p.age; return *this; } int age; }; //1 解决名称冲突 void test01() { Person p(18); cout << "年龄:" << p.age << endl; } //2 返回对象本身用*this void test02() { Person p1(10); Person p2(20); cout << "年龄:" << p2.age << endl; // 链式编程 p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); cout << "年龄:" << p2.age << endl; } int main() { // test01(); test02(); return 0; }
年龄:20 年龄:60
3、空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针;
如果用到this指针,需要加以判断保证代码的健壮性;
#include <iostream> using namespace std; //C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针; //如果用到this指针,需要加以判断保证代码的健壮性; class Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { // 防止空指针访问,导致程序崩溃 if (this == NULL) { return; } cout << "年龄:" << this->m_Age << endl; } int m_Age; }; void test01() { Person *p = NULL; p->showClassName(); p->showPersonAge(); } int main() { test01(); return 0; }
this is Person class
4、const修饰成员函数
常函数:成员函数后加const后我们称这个函数为常函数,常函数内不可以修改成员属性,成员属性声明时加关键字mutable后,在常函数中依然可以修改。
常对象:申明对象前加上const称该对象为常对象,常对象只能调用常函数。
#include <iostream> using namespace std; //常函数:成员函数后加const后我们称这个函数为常函数,常函数内不可以修改成员属性,成员属性声明时加关键字mutable后,在常函数中依然可以修改。 class Person { public: // this指针的本质是指针常量,指针的指向是不可以修改的 //const Person * const this; 成员函数后边的const,本质是修改this指正 void showPerson() const { cout << this->m_A << endl; // m_A=100; //常函数无法修改非mutable修饰的变量 this->m_B = 1000; } void showNum() { cout << m_B << endl; } int m_A; mutable int m_B; //常函数中可以修改 }; //常对象:申明对象前加上const称该对象为常对象,常对象只能调用常函数。 void test01() { // 常对象 const Person p1{}; p1.m_B = 200; // 常对象只能调用常函数 p1.showPerson(); // p1.showNum(); //常对象不可以调用普通成员函数,因为普通成员函数可以修改属性 }; int main() { test01(); return 0; }
四、友元
友元:让一个函数或类,访问另一个类中私有成员;关键字为friend;
1、全局函数做友元
#include <iostream> #include <string> using namespace std; //建筑物 class Building { // gooeGay函数是Building的好朋友,可以访问Building的私有属性 friend void gooeGay(Building &build); public: Building() { m_SittingRoom = "ke——ting"; m_BedRoom = "wo-shi"; } public: string m_SittingRoom;//客厅 private: string m_BedRoom;//卧室 }; //全局函数 void gooeGay(Building &build) { cout << "public: " << build.m_SittingRoom << endl; cout << "private: " << build.m_BedRoom << endl; } void test01() { Building building; gooeGay(building); } int main() { test01(); return 0; }
public: ke——ting private: wo-shi
2、类做友元
#include <iostream> #include <string> using namespace std; class Building; class GoodGay { public: GoodGay(); public: void visit(); Building *building; }; class Building { // GoodGay是本类的好朋友,可以访问私有属性 friend class GoodGay; public: Building(); public: string m_SittingRoom; //客厅 private: string m_BedRoom;//卧室 }; Building::Building() { m_SittingRoom = "ke——ting"; m_BedRoom = "wo-shi"; } GoodGay::GoodGay() { building = new Building; } void GoodGay::visit() { cout << building->m_SittingRoom << endl; cout << building->m_BedRoom; } void test01() { GoodGay gay; gay.visit(); } int main() { test01(); return 0; }
3、成员函数做友元
#include <iostream> #include <string> using namespace std; class Building; class GoodGay { public: GoodGay(); public: void visit(); void visit2(); Building *building; }; class Building { // GoodGay::visit()函数是本类的好朋友,可以访问私有属性 friend void GoodGay::visit(); public: Building(); public: string m_SittingRoom; //客厅 private: string m_BedRoom;//卧室 }; Building::Building() { m_SittingRoom = "ke——ting"; m_BedRoom = "wo-shi"; } GoodGay::GoodGay() { building = new Building; } void GoodGay::visit() { cout << building->m_SittingRoom << endl; cout << building->m_BedRoom; } void GoodGay::visit2() { cout << building->m_SittingRoom << endl; // cout << building->m_BedRoom; } void test01() { GoodGay gay; gay.visit(); } int main() { test01(); return 0; }
C++类和对象3:https://developer.aliyun.com/article/1548158?spm=a2c6h.13148508.setting.17.224d4f0e8YFWtB