C++类和对象

成员函数(方法)

成员函数的声明与定义

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

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

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

类的编译期两遍处理:

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

尾随返回类型

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

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

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

运算符重载

前缀自增

后缀自增

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

递归调用ptr->blala

C++11类型转换重载

类型转换重载

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

还可以用static_cast

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

需要加explicit

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

下面的obj等价于static_cast<bool>obj

避免二义性

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

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

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

  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: 表示左边的对象大于右边的对象。

  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++20能通过重载=推导出重载!=

但是反过来不行

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

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

类的其他特性:

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

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

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

聚合类

字面值常量类

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

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

隐式的类类型转换

explicit

标准库含有explicit的类

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

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

名称查找

域的逐级查找

逐级查找:

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

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

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

继承的名字查找

函数顺序的影响

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

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

解决方法:前面声明

名称隐藏

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

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

实参依赖查找(ADL)

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

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

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

类的静态成员

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

类的静态成员声明

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

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

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

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

2.内联静态初始化

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

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


 

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

友元

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

fun函数被视为函数的声明

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

隐藏友元的tricky

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

解决:ADL  传入类对象

默认成员函数

构造函数 

委托构造函数(Delegated Constructor)

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

默认构造函数的作用

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

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

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

默认实参和构造函数

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

移动构造函数

delete关键字

继承

静态类型和动态类型

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

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

实例:不能用ref调用fun2

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

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

虚函数

dynamic_cast:

Base类要用vtable

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

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

友元不能继承

继承的名字查找

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值