static

notion image
static member 被Class的所有实例共享
static: persist maintainance(持久存储) static的初始化构造命令只会执行和发生一次
  • static member 的类属性变量——必须在类外初始化定义,你在构造一个类的对象的时候,是不会自己自动初始化的; 可以通过类来访问: A::date
    • notion image
  • static function函数:只能访问/操作 static类型的成员变量;可以通过类来调用 A::function();

Operation Overloaded

operators 运算符本质上也是一种member function

notion image
这里面的 z=x+3 3其实是作隐式转换为z和x的类型
notion image
单目运算的参数表是空的(只有对象自己参与)

通过Global Function + friend来实现重载

notion image
  • 注意一定要用 const Type& 常量引用,不然不能接收临时对象——“const reference”
  • 能加const一定加上,包括函数不改变值的时候

特殊一点的[]运算符——“下标访问”

notion image
  • 返回值是你要访问的元素的引用 > 这种的一般都是要修改容器内元素的,所以返回引用,属于非const型函数,所以并不能用于访问const型的容器内的const元素
  • 所以往往还有另一种[]的重载!
在 C++ 中,[] 操作符的重载可以通过 const 和非 const 版本实现:
  1. const 版本
      • 允许修改对象的元素。
      • 返回类型通常是可变的引用(T&),支持 vec[i] = value 这样的赋值操作。
  1. const 版本
      • 适用于 const 对象,只允许读取,不允许修改。
      • 返回类型是常量引用(const T&),保证只能读取元素值,不能更改。
通过同时提供 const 和非 const 版本,确保 [] 可以既用于常量对象的访问(只读),也用于非常量对象的访问和修改,从而保证了灵活性和安全性。

重载时区分i++和++i

notion image
在设计重载函数的时候用一个参数在后面进行占位来区分
  • 有占位的是 i++
  • 没占位的是 ++i
notion image
notion image

逻辑比较运算——注意重用

  • 理论上只用定义一个 < 后面都可以逻辑重用
    • notion image

Assignment operator=

  • 编译器一般可以自动生成(每个member都递归调用=赋值operator)

特别特殊————functor () 小括号操作符

notion image

Lambda表达式

Lambda 表达式 是 可以直接当成一个函数function对象

Lambda 表达式的基本语法

  • 捕获列表 []:捕获当前作用域的变量,按值或引用捕获。
  • 参数列表 ():函数的参数。
  • 返回类型 >:指定函数的返回类型(可省略)。
  • 函数体 {}:定义具体逻辑。

示例:基础用法

捕获列表

  • 按值捕获 [x]:创建当前变量的副本。
  • 按引用捕获 [&x]:引用变量,修改会影响原变量。
  • [=]:按值捕获所有外部变量。
  • [&]:按引用捕获所有外部变量。
示例

应用场景

  • STL 算法
    • 回调函数:Lambda 可以用作临时函数对象。

    Lambda 表达式的底层本质就是——functor ()

    二者关系

    • Lambda 表达式:由编译器生成一个匿名类,并实现了 operator(),因此可以被像函数一样调用。
    • 仿函数:是一个显式定义的类,通过重载 operator() 使得对象具有函数调用行为。
    简洁示例对比: + Lambda 表达式
    • 等价的仿函数

      Type Conversion Operater 类型转换运算符

      1. 第一种:通过定义有参数的Ctor,可以实现类似类型转换的效果
      1. 第二种operator double() const {} 例如:
        1. Fraction::operator double() const{ return static_cast<double>(numerator) / denominator;}
          这种 operator double() const是不需要写返回值类型的
      • 关键词:explicit 声明为explicit的ctor或者类型转换符,不能再作自动的隐式类型转换,每一次转换必须都是显式的转换
      • 如果你两种都写了,会冲突报错Ambiguous编译器不知道用哪种

      对于<< >>流操作符的重载

      • 都是通过 全局函数重载+声明为友元函数来实现
        • 成员函数写不成

      一个operator<<重载的教训——要用 const tpye&型引用

      ### Grannypuppy: #file:fraction.cpp #file:fraction.h 为什么 cout<<f2-f3 会默认转换为double型输出。我的<<重载里面不是让他显式地转换为string输出么 ### GitHub Copilot: 问题出在 operator<< 的重载函数中。你将 Fraction对象转换为 std::string,但在 operator<< 函数中传递的是Fraction对象的引用。为了确保Fraction对象在输出时总是转换为字符串,你需要将 operator<< 函数的参数类型改为 const Fraction&。请修改 fraction.cpp 中的 operator<< 函数如下:
      同时,确保在 fraction.h 中的声明也一致: friend std::ostream& operator<<(std::ostream& os, const Fraction& fraction); 这样可以确保 Fraction 对象在使用 << 操作符时总是转换为字符串输出。 ### Grannypuppy: 我修改后确实成功了,这是为什么 ### GitHub Copilot: 这是因为在 C++ 中,运算符重载函数的参数类型会影响到函数的匹配和调用。具体来说: 1. 常量引用(const Fraction&
      • 使用常量引用可以确保传递给函数的对象不会被修改。
      • 这也允许函数接受临时对象(如表达式的结果),因为临时对象只能绑定到常量引用。
      2. 非常量引用(Fraction&)
      • 非常量引用要求传递给函数的对象必须是一个左值(即一个可以被修改的对象)。
      • 这意味着临时对象(如表达式的结果)不能绑定到非常量引用。
      在你的代码中,f2 - f3 产生了一个临时的 Fraction 对象。这个临时对象不能绑定到非常量引用(Fraction&),但可以绑定到常量引用(const Fraction&)。因此,将 operator<<的参数类型改为 const Fraction& 允许它接受临时对象,从而正确调用重载的 << 运算符并输出字符串表示。 # 总结:
      • 使用 const Fraction& 作为参数类型可以确保函数接受临时对象,并且不会修改传递的对象。
      • 这使得 `operator<<` 可以正确处理表达式的结果(如 f2 - f3),并调用 `std::string` 转换运算符来输出字符串表示。

      承接上文的临时变量

      左值(Lvalue)和右值(Rvalue)是C++中的两个基本概念。
      • 左值(Lvalue):表示一个在内存中有确定存储地址的对象,可以取地址。左值可以出现在赋值操作符的左边或右边。
      • 右值(Rvalue):表示一个不占据内存中确定存储地址的值,通常是临时对象或字面值。右值只能出现在赋值操作符的右边。
      在C++中,非const的左值引用(Fraction&)不能绑定到右值(临时对象),因为右值是临时的,生命周期很短,绑定到非const引用可能会导致悬挂引用(dangling reference)的问题。而const左值引用(const Fraction&)可以绑定到右值,因为const引用不会修改对象,编译器会延长临时对象的生命周期以确保引用的安全性。
      示例:

      总结

      • 非const左值引用(Fraction&)只能绑定到左值。
      • const左值引用(const Fraction&)可以绑定到左值和右值。
       
      Loading...