C++面向对象的三大特性:继承 多态 封装
具有相同性质的对象,可以抽象为类
封装的意义
- 将属性和行为作为一个整体,表现生活中的事物
- 将属性和行为加以权限控制
- 公共权限 成员 类内可以访问 类外可以访问
- 保护权限 成员 类内可以访问 类外不可以访问(子类可访问父类中保护内容)
- 私有权限 成员 类内可以访问 类外不可以访问(子类不可访问父类私有内容)
实例化:通过一个类创建一个对象的过程
成员属性设置为私有的优点
- 可以自己控制读写权限(选择在成员函数中提供set或get操作)
- 对于写权限 可以检测数据的有效性
构造函数的分类和调用
- 两种分类方式
- 按参数类型:有参构造和无参构造
- 按类型分:普通构造和拷贝构造
2.三种调用方式
- 括号法 Person p2(10); Person p3(p2);
注意调用默认构造函数时不要写(),这样编译器会认为是一个函数声明
- 显示法 Person p2=Person(10) ; Person p3=Person(p2);
- 隐式转换法 Person p4=10; 相当于Person p4=Person(10);
Person p5=Person p4;
静态成员——在成员变量和成员函数前加关键字static
- 静态成员变量
所有对象共享同一份数据
在编译阶段分配内存
类内声明,类外初始化
class Person {
public:
static int PersonNum;
};
int Person::PersonNum = 0;
有两种访问方式:1.通过对象进行访问 2.通过类名进行访问
int main() {
Person p;
cout << p.PersonNum << endl;
cout << Person::PersonNum << endl;
}
静态成员变量也有访问权限
- 静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量(否则无法区分到底是哪个 对象的)
class Person {
public:
static int PersonNum;
int age;
static void func() {
cout << PersonNum << endl; //可访问
cout << age << endl; //不可
}
};
拷贝构造函数调用的时机
- 使用一个已经创建完毕的对象来初始化一个新对象
- 值传递的方式给函数参数传值
- 以值方式返回局部对象
深拷贝和浅拷贝
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
类对象作为类成员
先构造类对象,再构造自身
先析构自身,再析构类对象
class Phone {
public:
string Pname;
Phone(string Pname) {
this->Pname = Pname;
}
};
class Person {
public:
string name;
Phone phone;
Person(string name, string Pname) :name(name), phone(Pname) {
}
};
成员变量和成员函数分开存储
C++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置
只有非静态成员变量 属于类的对象上
this指针:
隐含在每一个非静态成员函数内的一种指针,指向被调用的成员函数所属的对象
用途:
- 当形参和成员变量同名时,可用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用 return *this
const 修饰成员函数
常函数:
- 成员函数后加const后这个函数称为常函数(修饰的是this指针,让指针指向的值不可以修改)
- 常函数内不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数中依然可以修改
常对象:
- 声明对象前加const
- 常对象只能用常函数
友元
友元的目的——在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问
友元的三种实现:
- 全局函数做友元
在类中写全局函数的声明,在前边加上关键字friend
- 类做友元
在类中写class ClassName,在前边加上关键字friend
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息
- 成员函数做友元
和全局函数做友元相比,在函数名前加上作用域,说明是成员函数