C++面向对象编程(中)

C++面向对象编程(中)

1. 类型转换

1. operator 转换函数
  • 写法:operator typename() const {…}
    • 不需要写return类型,typename相当于返回类型;
    • 一般转换函数不会改变数据,所以要加const;
  • 对于 double d = 4 + f:
    • 由于整形在前面,所以编译器会先寻找,有没有全局的 “+” 操作符函数,并且两个类型对应;
    • 找不到,接着找转换函数;
  • 在下面的例子中找到了转换函数,将 f 转换为double类型。
    在这里插入图片描述
2. 隐式转换构造函数
  • 需要有 non-explicit-one-argument ctor
    • non-explicit:构造函数最前面没有explicit关键字;
    • one-argument:构造函数最少需要传递一个实参(下图有两个实参,但其中一个有默认值);
  • 对于 double d = f + 4:
    • 编译器会找到 “+”操作符成员函数,但参数是Fraction;
    • 之后再找整型能否转换为Fraction。
      在这里插入图片描述
3. operator 转换函数和隐式转换构造函数并存
  • 可能同时有多种方案可以使用,存在二义性的转换,导致编译器报错。
  • 对于 Fraction d2 = f + 4(下图):
    • 第一种:调用Fraction的“+”操作符成员函数,再将 4 转换为Fraction ;
    • 第二种:将f转换为double,为了把double + int转换为Fraction;先将double + int转为int,再转为Fraction。
      在这里插入图片描述
4. explicit关键字
  • 不允许隐式转换,这个例子不允许将整型(double)转换为Fraction;
    在这里插入图片描述

2. 类的行为像指针(pointer-like classes)

1. 实现类的行为像指针
  • 一般指针的普遍操作:“*” 操作符和 “->” 操作符;
  • 使类的行为像指针:
    • 操作符重载:重载 “*” 操作符和 “->” 操作符
2. 关于智能指针
  • 类内容:
    • 数据:模板类T的指针 T* px;
    • 操作符重载:
      • T& operator*() const {
        	return *px;
        }
        T* operator->() const {
        	return x;
        }
        
  • 注意点(->操作符的特殊性):
    • ->作用后得到结果,->还会继续作用下去!!!
    • 下图是使用 ->操作符的例子:
      • /*
        sp调用->操作符,得到px;
        但->操作符已经消耗了,为什么还会一个->操作符;
        
        ->操作符的特殊性:
        	->作用后得到结果,->还会继续作用下去!!!
        */
        sp->method();  // 相当于px->method();
        

在这里插入图片描述

2. 关于迭代器
  • 以双向链表为例,存放上图的Foo类型对象;
  • 操作符重载:
    • // node为当前指针
      // *操作符:取出数据
      reference operator*() const {
      	return (*node).data;
      }
      // 调用*操作符取出数据,返回数据的指针
      pointer operator->() const {
      	return &(operator*());
      }
      

在这里插入图片描述

3. 类的行为像函数(function-like classes)

  • 类重载 () 函数操作符
    在这里插入图片描述

4. member template

  • member Template:

    • 类本身是一个模板;
    • 它当中有一个成员函数F,F又是另一个模板(和类的模板参数不一样)
      在这里插入图片描述
  • 成员模板的作用

    • 为了让类更有弹性,让模板类型为子类的可以拷贝构造到模板类型为父类的。
    • Derived1是Base1的子类;Derived2是Base2的子类;
    • p的类型:pair<Derived1, Derived2>;
    • p2的类型:pair<Base1, Base2>;
    • 问题:
      • 可不可以使用p作为p2的初始值?
      • 反过来呢?
    • 答案:
      • 可以(因为子类可以转换为父类???但这不是用父类指针接受,会发生截断);
      • 反过来不行。
        在这里插入图片描述
  • 另一个例子:用指针模拟向上转型
    在这里插入图片描述


5. 模板泛化

1. 全特化
  • 对全部模板参数进行特化;
  • template<>;
  • 也可以特化void版本
    在这里插入图片描述
2. 偏特化
  • 个数上的偏特化:

    • 个数上偏特化指:比如两个模板参数,绑定了一个后,变成了一个模板参数;
    • 偏特化要按照从左到右顺序,依次特化:不能特化第一个,跳过第二个,特化第三个。
      在这里插入图片描述
  • 范围上的偏特化:

    • 这两个版本的T不是同一个T,不要混淆。
      在这里插入图片描述

6. template template parameter

  • 介绍:

    • 模板的模板参数:模板参数本身就是类模板;
    • 下图中两个模板参数T是不一样的,不要写成一样的更容易理解;
    • 模板的模板参数中的T没有用到;
    • 下图中的private数据,使用第一个模板参数用于第二个模板参数的实例化,仅仅是特例;可以用类模板内的任何类型来实例化模板的模板参数。(Container c)
  • 作用:

    • 模板模板参数,常用于传递没有定义内容类型的容器。
  • 使用:

    • 传入list失败的原因是,是因为list容器实质上是有第二参数的,虽然第二参数有默认的参数,正如我们平常使用的那样,只需要指定一个参数,但是在这里无法通过编译。
      在这里插入图片描述
  • 注意点:

    • 这不是模板模板参数;
    • 在使用时,传入的list已经不是模板了,模板参数已经固定。
      在这里插入图片描述

7. variadic templates(可变模板参数)

  • 顾名思义,接受数量不定的模板参数;
  • 注意模板参数的声明和使用写法(…);
  • sizeof...(args)获取包含了多少个参数。
    在这里插入图片描述

8. auto

  • 靠编译器自动推导变量的类型;
  • 注意:写auto一定伴随赋值操作,不然编译器无法推导类型。
    在这里插入图片描述

9. range base for

  • 基于范围的 for(增强for);
    在这里插入图片描述

10. reference

  • 指针的意义是指向

  • 引用的意义是代表,是别名,意味着它代表谁,它就是谁;

  • 引用重点:

    • 引用必须有初始化;

    • 引用不能重新代表其他对象:

      • 一旦它指定为某一个对象的引用后,就不能更改了。但是,可以用这个引用来改变它的对象的值,从而达到引用的目的——作为变量对象的别名;
      • 下图的r = x2;就是改变它代表的对象x的值。
    • 编译器对引用的实现是通过指针实现的:

      • 但在逻辑上,要让引用是别名,即引用代表int,那它就是int;
      • 所以编译器会制造假象,令引用的大小 == 它代表对象的大小,引用的地址 == 它代表对象的地址;但实际上引用只是一个指针的大小;
      • 三种数据类型(常规,引用,指针)在内存中的大致表现(下图):
        在这里插入图片描述
    • 测试举例(编译器的假象):

      • 关注引用变量和它代表的变量;
        在这里插入图片描述
  • reference常见用途:

    • reference通常不用于声明变量,而用于传递参数和返回类型的描述;
    • 函数重载需要看函数签名是否可以区别:
      • 函数签名组成部分:包括函数名,参数类型,参数个数和顺序,以及它所在类和命名空间;
      • 函数签名不包括返回类型(看下图);
      • reference不能区分函数签名,参数前面的const也不能区分函数签名;二者在调用的时候形式没有区别,如果可以区分函数签名,编译器就区分不出来;(矛盾)
    • 参数后的const(灰色位置),即const member function可以区分函数签名。
      在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值