C++面向对象—封装(2)
Date:2021.9.30
Author:lqy
文章目录
一、初始化列表:
-
初始化列表简介:
C++面向对象编程提供初始化列表完成类似于有参构造函数的功能
-
代码示例:
class Person { public: int a; int b; int c; public: Person(int a, int b, int c) { /*带参构造函数*/ this->a = a; this->b = b; this->c = c; } /*初始化列表->1. 类构造初始值赋值 2. 类构造用户输入赋值*/ Person() :a(10), b(10), c(10) {} Person(int aa, int bb, int cc) :a(aa), b(bb), c(cc) {} };
二、类对象作为类成员:
-
类对象作为类成员简介:
-
构造函数->先创建内部成员,进而创建外部对象
-
析构函数->先析构外部对象,进而析构内部成员
-
-
代码解析:
class Phone { public: string brand; public: /*Phone类的无参和有参构造函数*/ Phone() {} Phone(string name) { this->brand = name; } }; class Person { public: /*类对象作为成员属性*/ string name; Phone p; public: /*带参构造函数*/ Person(string name, string pName) { this->name = name; this->p.brand = pName; // 赋值给对象的特定属性 } /*class借助于初始化列表方法实现class对象创建*/ /*p(pName)->采用隐式转换法 Phone p = pName;*/ Person(string Personname, string pName) :name(Personname), p(pName) {} };
三、静态成员变量static
-
静态成员变量简介:
- 静态成员变量特点:
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外进行初始化
- 静态成员变量的访问形式:
- 借助于对象进行访问
- 借助于类名进行访问
-
代码声明:
class Person { /*static静态成员变量同样具有访问属性,private无法在类外进行访问*/ /*成员变量类内声明*/ public: static int a; private: static int b; }; /*成员变量类外初始化*/ /*类外初始化,添加特定类的作用域Person::*/ int Person::a = 100; int Person::b = 600; void test01() { Person p; Person p2; /*所有对象p和p2共享同一份数据a和b*/ cout << p.a << endl; //output->100 p2.a = 200; cout << p.a << endl; //output->200 } void test02() { Person p; /*借助于对象和类名进行访问*/ cout << p.a << endl; cout << Person::a << endl; }
四、静态成员方法
-
静态成员方法简介:
- 与静态成员变量类似,所有对象共享同一个静态函数
- 静态成员函数仅能访问静态成员变量
-
代码示例:
class Person { public: /*静态成员方法与静态成员变量类似,同样具有访问权限---private,public,protetced*/ static void func() { cout << "函数调用" << endl; a = 100; // 静态成员函数可以访问静态成员变量 // b = 100; // 静态成员函数不可以访问非静态成员变量 /*静态成员变量属于特定的对象,静态函数属于所有对象,因此静态成员函数不能访问非静态成员变量*/ } static int a; //静态成员变量 int b; }; int Person::a = 0; //类外初始化 void test01() { Person p; /*静态成员函数两种访问形式->1. 通过特定对象访问 2. 通过类名访问*/ p.func(); Person::func(); }
五、成员变量和成员函数分开存储
-
内部存储简介:
- 只有非静态成员变量属于类的实例化对象上
- 静态成员变量本质上仅有一份,不属于任何特定对象,当然也不占用本对象内存
- 静态成员函数和非静态成员函数均不占用本对象内部空间,不属于特定的对象
-
代码示例:
class Person { /*成员变量和函数->(1. 静态 2. 非静态)*/ int a; static int b; void func(){} static void func(){} }; void test01() { Person p; cout << sizeof(p) << endl; // output->1 /*空对象占用内存空间:1 (在Person类中未添加任何成员的情况下)*/ /*编译器给每个对象分配一个内存空间,为区分空对象占内存的位置,每个空间都应该有一个独一无二的空间*/ } void test02() { Person p; cout << sizeof(p) << endl; //output->4 /*仅有非静态成员变量int a属于该实例化对象,int类型占用4个字节*/ /*其余的静态成员变量,静态和非静态成员方法均不属于此对象,不占用此内存空间*/ }
六、面向对象之This指针
-
this指针简介:
- this指针指向被调用函数所属的对象
- this指针隐含在每一个非静态成员函数的内部,不需要定义,直接使用即可
-
this指针应用场景:
- 解决形参与实参名称冲突问题
- 返回对象本身
-
代码示例:
class Person { public: int age; Person(int age) { /*this指针指向被调用函数所属的对象,即this->age指Person类的age属性,age指的是构造函数传进的参数*/ this->age = age; } Person& PersonAddage(Person& p) { this->age += p.age; /*this指针指向被调用函数所属的对象,本质上为一个指针,解引用之后代指本对象,并使用引用方式接收*/ return *this; } }; void test01() { Person p(10); Person p2(10); p2.PersonAddage(p).PersonAddage(p).PersonAddage(p); cout << p2.age << endl; }
Tips:
PersonAddage函数的返回值方式会影响
p2.PersonAddage(p).PersonAddage(p).PersonAddage(p);
代码的输出:
- 假设以引用的方式返回,每次返回对象引用,即可以完成本对象的年龄age叠加
- 假设以值的方式返回,每次会多次调用拷贝构造函数,创建诸多副本,无法完成原始对象年龄的多次叠加
七、空指针访问成员函数
-
内容简介:
创建Person对象指向空指针NULL,则内置的this指针指向为空,因此程序运行过程中代码会崩溃,为提高程序健壮性,可以设置检测代码,避免程序崩溃。
-
代码示例:
class Person { public: void showclassName() { cout << "this is Person class" << endl; } void showPersonage() { /*假设this指针对象指向为空NULL,直接return结束函数,避免程序崩溃*/ if (this == NULL) { return; } cout << age << endl; } public: int age; }; void test01() { Person* p = NULL; // this指针未指向任何对象(Person指针为NULL) /*未涉及class内部任何成员变量或函数,因此无论是否this指向为NULL,均可以成功运行*/ p->showclassName(); /*clss类内部定义的所有成员变量和方法前方均默认添加this->,因此必须添加代码检测NULL*/ /*添加检测代码后,showPerson函数可以成功运行,未添加程序崩溃*/ p->showPersonage(); }
八、面向对象class的const修饰符
-
const修饰简介:
- const修饰成员函数,为常函数,常函数内不能修改成员属性,如果想在常函数内修改成员属性,需要添加mutable修饰符
- const修饰class对象,常对象仅能调用常函数
-
代码示例:
class Person { /*this指针的本质为指针常量,指针的指向是不可以进行修改的*/ /* const Person * const this 双const修饰,this指针的指向和指向的具体值均不能进行修改*/ public: /*添加const修饰符修饰成员函数*/ void showPerson() const { /*常函数内不能修改成员属性,仅能修改mutable修饰符修饰的成员属性*/ //a = 100; //failed b = 100; } void func(){} public: int a; mutable int b; }; void test01() { /*const修饰符修饰class对象,变为常对象*/ const Person p{}; /*常对象仅能不能修改普通成员属性,仅能修改mutable修饰的成员属性*/ // p.a = 100; //failed p.b = 100; /*常对象仅能调用常函数*/ p.showPerson(); //p.func(); //failed }
-
-
-