/
...
/
/
七. OOP(类)
Search
Try Notion
七. OOP(类)
Universal
对象/类
封装和隐藏数据
多态
继承
代码复用
类的组成
类声明:成员变量,成员函数的声明(放于头文件)
类方法定义:成员函数的实现(放于cpp文件)
类内联:定义在类声明内的函数默认为类内联,当然,也可通过inline在类声明外定义(必须在同一文件中)
访问控制
private
默认访问控制符—不加任何访问控制符即为private
同类不同对象也可访问private成员
public
protected
定义类成员时使用域解析运算符:: 调用类成员时根据情况使用直接成员运算符. 间接成员->
const类
由于const类对象所有成员不能修改,其不能调用其成员函数
所以在进行类成员函数调用时,必然会涉及隐式的参数传递,若为const对象 则该隐式传递要保证不修改const对象的内容
通过类似 void show() const 的语法来保证
构造函数—-析构函数
当初始化类对象时自动调用构造,删除时自动删去
调用方式/初始化类型
//显式 Stock var1 = Stock(1,2) ; //隐式,初始化列表,单参数时也可直接赋值 Stock var1 = {1, 2} ; //动态存储 显式 Stock *var1 = new Stock(1, 2) ; //对象数组初始化 Stock var1[3] = { Stock(1, 2), Stock(1, 2), Stock(1, 2) } //对象数组初始化(列表初始化形式) Stock var1[3] = { {1, 2}, {1, 2}, {1, 2} }
Copy
C++
列表初始化一定要和某个构造函数相匹配
默认构造函数,
当并没有初始化时候,自动调用默认构造函数,其函体为{ } 等于不做任何事
要修改默认构造函数可以重载一个无参数的构造函数或者有所有参数都有默认值(只能有一个)
复制构造函数(参数为同类的构造函数)
函数传参时,同类初始化时,函数返回时会调用(新建临时变量),但部分情况下不会新建临时变量(const或引用)
默认为浅复制,一定要重载为深复制
如果不进行深复制,则会出现两个变量指向同一个对象的情况,假设一个是临时变量,销毁时,调用析构,则剩下哪个变量的内容会被破坏
类常量
由于类定义中const常量只有在对象创建才创建,且无法被所有对象共享
由于不在类中不能通过成员运算符.访问,需要通过作用域解析运算符::
枚举方法
我们可以声明枚举来变相声明常量,在需要的地方会化为整型
由于不真的创建枚举量,只是借用其符号定义,也可声明为匿名枚举
枚举类方法
//避免枚举符号定义重复比如 enum a { c=10, d=20 } ; enum b { c=10, d=20 } ; //invalid //可通过类枚举 enum class a { c=10, d=20 } ; enum class b { c=10, d=20 } ; //使用时 a var1 = a::c ; b var2 = b::c ; //但是注意,该枚举不会自动转换整型,需要显式转换 //比如: int(a::c)
Copy
C++
类初始化
成员列表初始化
当类成员含有const对象或被声明为引用时,必须在创建时初始化
而析构函数函数体中,所作的都是创建后工作,故不能给const量赋值
需要借助成员列表初始化
class myclass { private: const int a ; ... } myclass::myclass(int b) : a(b) {...}
Copy
C++
仅在构造函数中该语法有效
初始化顺序为其声明的顺序,而不是初始化排列的顺序
运算符重载
语法operateor[op](parament) 比如operateor+()
重载限制
不能新建运算符
不能重载标准运算符(两个操作数至少有一个是用户定义的,比如不能重载int+int)
赋值= 函数调用() 下标运算[] 间接引用-> 仅支持通过成员函数重载
五则运算+-*/% 和对应自操作运算符+=... 逻辑运算>=< 动态分配运算符new delete new[] ... 可重载
友元函数
可以访问private成员
在类声明中加入friend 关键字的函数,但是在函数定义中不加入(区别static声明函数)
虽然在类声明中但不是成员,不适用成员运算符.
对于友元重载,需要传递两个操作数,对于非友元而言,其中一个通过this指针
比如operator+(int a, myclass b) operator+(int a)
🤔当一个友元函数完全以内联形式位于声明区域时候,他虽然形式上是成员函数,也可访问private,但不是成员函数,没有隐含this指针传参
赋值运算符重载
在赋值时调用
写法上同复制构造函数类似,但有几点要区别
目标对象可能已分配了数据,要使用delete[]来删除以前的数据
避免将对象赋给自身,否则在完成赋值前,可能析构函数已将数据释放
返回一个指向对象自身的引用return *this 原型为自身引用 MyClass &
对于初始化而言,时候调用取决于语法,有可能仅调用复制构造,也有可能调用复制构临时变量,然后将其赋值给新建变量
MyClass a ; MyClass b = a ; //赋值初始化,根据实现可能使用赋值运算符重载,但一定会调用复制构造 MyClass b = MyClass(a) ; //显式调用复制构造 MyClass b(a) ; //另一种初始化
Copy
C++
对于非同类赋值重载,可提升效率
对比如下
类的类型转换
其他类→本类
根据构造函数是否有提供其他类的构造函数吗
是否其他类能够自动类型转换成有提供的构造函数<关联函数重载解析>
可通过explicit 禁用隐式的自动转换
本类→其它类
特殊函数,转换函数operateor typename()
可以在本类的public中声明如
class A { private: ... public: operateor int () const ; operateor double () const ; }
Copy
C++
如果存在二义性,比如可转换为double int,而cout都可以接受,需要显式转换,自动转换会被禁用