C++类和对象

成员函数(方法)

C++类和对象_第1张图片

成员函数的声明与定义

在C++中,类内部定义的成员函数(包括普通成员函数和静态成员函数)在默认情况下被视为隐式内联(Implicitly Inline)。

隐式内联的意思是,编译器有权选择是否将类内部定义的成员函数进行内联展开。一般来说,对于较小的、简单的成员函数,编译器会更倾向于将其内联,以减少函数调用的开销。这并不是绝对的规则,编译器可能会根据具体情况做出决定。

如果在类内定义 隐式内联 如果在类外 则不是

类的编译期两遍处理:

类的编译期两遍处理通常是指在两个阶段进行处理:一次是类的声明阶段,另一次是类的定义阶段。这种两遍处理的方式是为了支持在类声明时使用成员函数的返回类型和参数类型,而不需要等到实际的成员函数定义之后

C++类和对象_第2张图片

尾随返回类型

尾随返回类型(Trailing Return Type)是指在函数定义中使用尾部语法来明确指定函数的返回类型。这种语法使用 auto 关键字和尾随 -> 符号,使得返回类型放在函数参数列表之后,函数体之前。

C++类和对象_第3张图片

成员函数用尾随返回类型推导时 编译器会自动去该类域找 MyRes类型

C++类和对象_第4张图片

成员函数基于引用限定符的重载

C++类和对象_第5张图片

运算符重载

C++类和对象_第6张图片

C++类和对象_第7张图片

前缀自增

C++类和对象_第8张图片

后缀自增

C++类和对象_第9张图片

C++类和对象_第10张图片

重载-> 只能返回类或类的指针

递归调用ptr->blala

C++类和对象_第11张图片

C++11类型转换重载

C++类和对象_第12张图片

类型转换重载

注意:要加const 否则const对象会编译不过

C++类和对象_第13张图片

还可以用static_cast

歧义:没有完美匹配的重载运算 有多种转换方式

需要加explicit

C++类和对象_第14张图片

例外:在条件判断中 编译器能转换成bool类型

C++类和对象_第15张图片

下面的obj等价于static_castobj

C++类和对象_第16张图片

避免二义性

1.最好不要创建两个转换源都是算术类型转换

2.不要构建两个类之间的相同的转换

C++类和对象_第17张图片

C++类和对象_第18张图片

补充:转换的优先级如下:

  1. 精确匹配
  2. const 转换。
  3. 类型提升
  4. 算术转换
  5. 类类型转换

C++20 的==和<=>重载

<=>运算符介绍

<=> 运算符返回的类型是一个有序比较结果,即 std::strong_orderingstd::weak_orderingstd::partial_ordering。这些类型的具体取值表示如下:

  • std::strong_ordering::equal: 表示两个对象相等。
  • std::strong_ordering::less: 表示左边的对象小于右边的对象。
  • std::strong_ordering::greater: 表示左边的对象大于右边的对象。

C++类和对象_第19张图片

C++类和对象_第20张图片

  1. std::strong_ordering

    • 用于强顺序比较,包括相等、大于和小于三种情况。
    • 对于 a <=> b,如果 a 等于 b,则返回 std::strong_ordering::equal
    • 如果 a 大于 b,则返回 std::strong_ordering::greater
    • 如果 a 小于 b,则返回 std::strong_ordering::less
  2. std::weak_ordering

    • 用于弱顺序比较,包括相等和不可比较两种情况。
    • 对于 a <=> b,如果 a 等于 b,则返回 std::weak_ordering::equivalent
    • 如果 ab 不可比较,则返回 std::weak_ordering::unordered

3.部分顺序有以下几种可能的结果:

  • std::partial_ordering::equivalent: 表示对象相等。
  • std::partial_ordering::less: 表示左边的对象小于右边的对象。
  • std::partial_ordering::greater: 表示左边的对象大于右边的对象。
  • std::partial_ordering::unordered: 表示对象之间的比较关系无法确定,即它们不可比较。

部分比较 unordered 为浮点数的NAN引入

C++类和对象_第21张图片

另外,C++20能通过重载=推导出重载!=

但是反过来不行

C++20隐式交换参数顺序

C++类和对象_第22张图片

<=>重载示例 注意返回类型

C++类和对象_第23张图片

类的其他特性:

1.类内部定义的函数自动inline

2.类内成员函数可以被重载

3.可变数据成员 :mutable关键字 用于统计函数调用次数

C++类和对象_第24张图片

聚合类

C++类和对象_第25张图片

字面值常量类

constexpr函数:可以在编译期执行也可以在运行期执行

要求函数体的内容都能在编译期执行

C++类和对象_第26张图片

C++类和对象_第27张图片

隐式的类类型转换

explicit

C++类和对象_第28张图片

标准库含有explicit的类

接受单一参数的const char* 的string构造函数不是explicit

接受一个容量参数的vector构造函数是explicit

名称查找

C++类和对象_第29张图片

域的逐级查找

逐级查找:

限定在MyNs域里 编译器已经找到了fun函数 就不会考虑域外的函数

如果在名字空间里查找不到 就会再外围查找

C++类和对象_第30张图片

基类和派生类会形成域的嵌套 先找小域(派生类)再查找大域(基类)

继承的名字查找

C++类和对象_第31张图片

函数顺序的影响

ticky:由于编译器是从上到下编译 调用g时 编译器在MyNs空间找不到fun于是就会在外围找fun(int)

查找只会在已经声明的集合进行

C++类和对象_第32张图片

解决方法:前面声明

C++类和对象_第33张图片

名称隐藏

名称隐藏是指在某个作用域内定义了一个与外部作用域相同名称的实体(如变量、函数、类),导致外部作用域的同名实体被隐藏。这个概念有时也称为"名称遮蔽"或"名字屏蔽"。

查找只会在已经声明的集合进行

C++类和对象_第34张图片

实参依赖查找(ADL)

当你调用一个函数并提供了实参,编译器不仅仅查找函数名,还会查找与实参关联的命名空间,这被称为实参依赖查找。这个机制的目的是使得与实参相关的函数能够被正确地解析,即使这些函数不在调用点的作用域中。

例子:g调用了obj obj是个类 则编译器将会把obj的域纳入查找范围内

C++类和对象_第35张图片

换成系统内置类型则会报错 编译器不会查找

C++类和对象_第36张图片

类的静态成员

C++类和对象_第37张图片

应用:与类本身关联 但不需要与每个对象关联 例如:利率

类的静态成员声明

1.静态成员类内声明 类外定义

C++类和对象_第38张图片

C++类和对象_第39张图片

C++98 const静态成员初始化:

通常类的静态成员不能进行类内初始化 然而可以为静态成员提供const整数类型的类内初始值

即使一个常量数据成员在类内初始化了 通常在类外也应该定义该成员

C++类和对象_第40张图片

C++类和对象_第41张图片

2.内联静态初始化

静态成员变量的 inline 关键字用于在头文件中定义静态成员变量,从而避免在多个编译单元中出现重复定义的问题。

C++类和对象_第42张图片

静态成员可以作为默认实参

C++类和对象_第43张图片


 

静态成员函数可以返回静态数据成员

C++类和对象_第44张图片

友元

C++类和对象_第45张图片

类内首次声明友元类或友元函数

fun函数被视为函数的声明

C++类和对象_第46张图片

使用限定名称引入友元并非友元类或者友元函数的声明

C++类和对象_第47张图片

隐藏友元的tricky

编译错误:只有定义 没有声明

C++类和对象_第48张图片

解决:ADL  传入类对象

C++类和对象_第49张图片

默认成员函数

构造函数 

委托构造函数(Delegated Constructor)

C++类和对象_第50张图片

C++类和对象_第51张图片

C++类和对象_第52张图片

初始化顺序与声明顺序相关 与初始化列表顺序无关

C++类和对象_第53张图片

默认构造函数的作用

在实际中如果定义了其他构造函数 那么最好也提供一个默认构造函数

注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数

C++类和对象_第54张图片

派生类中删除的拷贝控制与基类的关系

默认实参和构造函数

如果一个构造函数为所有参数提供默认实参,则他实际上也定义了默认构造函数

C++类和对象_第55张图片

C++类和对象_第56张图片

C++类和对象_第57张图片

移动构造函数C++类和对象_第58张图片

C++类和对象_第59张图片

C++类和对象_第60张图片

C++类和对象_第61张图片

delete关键字

C++类和对象_第62张图片

继承

静态类型和动态类型

静态类型:编译期确定的类型 

动态类型:运行期确定的类型

实例:不能用ref调用fun2

C++类和对象_第63张图片

C++类和对象_第64张图片

C++子类对象的构造过程。先调用父类的构造函数,再调用子类的构造函数,也就是说先初始化父类的成员,再初始化子类的成员。

若父类没有默认的构造函数,子类的构造函数又未调用父类的构造函数,则无法编译

虚函数

C++类和对象_第65张图片

dynamic_cast:

Base类要用vtable

基类的指针转为派生类的指针:如果基类指针指向派生类地址 转换成功 否则返回空指针

基类的引用转为派生类的引用同理..... 否则抛异常

C++类和对象_第66张图片

C++类和对象_第67张图片

友元不能继承

C++类和对象_第68张图片

C++类和对象_第69张图片

继承的名字查找

你可能感兴趣的:(c++,开发语言)