C++程序设计语言学习笔记(二)

本文深入探讨C++程序设计的核心概念和技术,包括抽象机制、运算符重载、类层次结构、模版以及异常处理等内容,并强调程序设计思想的重要性。

C++程序设计语言

该书主要介绍C++语言的基础以及如何利用它进行程序设计。学习任何一本语言如果只沉浸在语言本身特征,你的收获会比较小,关键是程序设计思想。里面提到的一句话很重要“对于程序语言设计和设计技术的理解远比细节的理解更重要,而这种理解的根本是时间和实践”。一般程序设计都会有三个过程:分析、设计、编码。一般程序员开始的时候花在分析和设计上的时间较少,开发之初就上手编程,容易照成后期维护修改比较困难,这种程序员一般用10%分析,20%设计,30%编码,40%bug加维护;对于一个高级程序员来说会花40%分析,40%设计,20%编码加维护。

第二部分:抽象机制

运算符重载

  • 不能被重载的运算符
    • 作用域解析(::)、成员选择符(.)、通过到成员的指针做成员选择(.*)
    • 不能重新定义新的操作符来表达某种含义
  • 二元操作符可以解析为:a@b可以理解为a.operator@(b)或者operator@(a、b)
    • 需要选择其中一个进行解析
    • 如果两者均有定义,按照一定的重载规则进行选择
  • 运算符重载的选择
    • 成员函数:像[]\=()\->一般均定义为非静态成员函数,来保证第一个参数为左值
    • 非成员函数:如果某个运算符想接受内部类型为第一个参数,一般定义为非成员函数
  • 转换运算符
    • 功能:提供两种类型之间的转换
    • 方式:x::operator T(),可以将类型x转换为T,无显式返回类型,需要返回转换后的结构
    • 一般不建议使用,通过有意义的函数可以完成相应功能,如果感觉不美观时,考虑它
  • 友元
    • 可以定义某个函数、某个类的成员函数、某个类为类X的友元,友元作用域内均可以访问到X的私有成员
    • 友元函数VS成员函数的选择:哪种方便用哪种。
  • 基本运算符
    • 复制构造函数-如果没有显示定义,则编译器会自动生成
  • 下标运算符
    • 其重载必须是成员函数
  • 函数调用
    • 函数对象:一种可以像函数一样使用的对象。其实是一个对象,不过是重载了()方法
    • 操作符()的重载必须是成员函数。
  • 间接运算符
    • ->返回内部对象的指针
    • 其重载必须是成员函数
  • 增量和减量运算符
    • 该类运算符是唯一一个能够作用于变量的前后
    • 通过参数中添加形参int来表明后置运算符

派生类

  • 成员函数,同名成员函数会被覆盖,不会被重载。
  • 构造函数和析构函数
    • 如果无参数构造函数时,子类必须通过初始化列表显示调用基类构造函数
    • 对象构造的顺序:基类、本类成员、派生类本身。析构的顺序严格相反。
    • 构造函数不被继承,如果没有默认会构造一个
  • 复制
    • 复制构造函数和赋值运算符,默认会构造不会被继承。
  • 虚函数
    • 函数参数必须保持相同,返回值可以略为不同
    • 实现多态:必须通过基类指针或者引用的方式
  • 抽象类
    • 类中定义了一个或者多个纯虚函数(=0),即为抽象类。
    • 不能定义抽象类的对象
    • 常用于实现界面,即抽象接口

模版

  • 模版定义:通过template<class C> 进行定义模版函数或者模版类,C的作用域直到区域结束,所以成员函数在不同文件定义时需要带上模版
  • 模版实例化和专门化
    • 实例化:通过一个模板类和模版参数得到类声明的过程
    • 专门化:针对一个模版参数的模版版本
  • 模版参数:
    • 可以为多个
    • 模版参数也可以有默认值
    • 可以为常见类型,如int template<class T, int i>此时的i必须为一个常量值。
  • 函数模版
    • 提供更通用的方法或者算法
    • 定义:template<class T> void f()
    • 使用:f<char>()
    • 当存在多个参数,后面的参数可以不给出,但必须能推断出
    • 当存在多个同名的模版函数时,调用规则
      • 尽量选择更加专门的模版进行解析。
  • 专门化
    • 定义用户特需模版,例如定义 template<class T> class vector的一个专门化 template<>class vector<void*>
    • 完全专门化template<> class vector<void*>
    • 部分专门化template<class T> class vector<T*> : private vector<void*>
    • 函数专门化

异常处理

  • 能不用异常处理则不用

类层次结构

  • 多重继承
    • 继承自多个基类的派生,可以同时继承两个基类的成员
    • 基类中相同的成员,通过限定符进行调用,例如AB均有成员函数f(),使用时A::f(),不能通过参数类型进行区分
    • 重复基类:可以通过类名进行限定,也可以通过虚基类的方式解决
    • 虚基类:可以使得共享基类有一个备份,实现方式class A : public virtual B--砖石继承
    • 总之:如果需要基类不应该重复应该使用虚基类,否则使用正常基类。
  • 访问控制
    • private:只能被类成员和友元函数使用
    • protected:能被类成员、友元以及派生类的成员和友元使用
    • public:可以被任何成员使用
    • 对于基类的保护 class A :{private\protected\public} B
      • public:使得A是B派生出来的一种类型,B中的public变量可以有任何函数调用。B中的protected可以有A中的成员以及友元函数调用。任何函数均可以将A*转换为B*
      • protected:B中的public和protected成员仅可以被A中的成员函数以及友元使用,只有成员或者友元函数可以将A*转换为B*
      • private:B中的public和protected成员仅可以被A中的成员函数以及友元使用(A的派生类型不能使用),只有成员或者友元函数可以将A*转换为B*
    • 多重继承的访问控制:
      • 某成员只有有一种途径可以访问到,则其就可以被访问
  • 运行时类型
    • dynamic_cast<T*>(p):如果p是类型T或者是T的某派生类指针,可以正常转换,否则返回0
    • 其中要求p为一个 到多态类型的指针,即包含虚函数
    • 如果是引用类型,转换失败时抛出bad_cast异常
  • 类对象的构造和析构
    • 在构造和析构函数中尽量不调用虚函数,不会产生多态行为--类本身还没有构造完成
  • 指向成员的指针
    • 能够间接引用类成员
    • typedef void (A::*pf)()
    • pf = &A::f()
    • A a; a.*f()
  • 自由存储
    • 用户可以自定义operator new(size_t)和operator delete(size_t)运算符来分配空间

构造函数不能为虚函数,构造时必须知道确切的类型

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值