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)运算符来分配空间
o 构造函数不能为虚函数,构造时必须知道确切的类型
本文深入探讨C++程序设计的核心概念和技术,包括抽象机制、运算符重载、类层次结构、模版以及异常处理等内容,并强调程序设计思想的重要性。
4602

被折叠的 条评论
为什么被折叠?



