【侯捷】C++面向对象程序设计
本系列相关链接:
【侯捷】C++11
0. 课程目标
- 培养正规、大器的编程习惯
- 良好方式编写class,做“有生产力”的开发工程师
- 学习class之间的关系
c++98 (1.0)
c++11 (2.0) <–目前大多数公司使用,成熟、通用
c++14 c++17 c++20
C++包括C++语言、C++标准库;
C++class分两种,一种带指针(资源)(例如string),一种不带指针(例如complex),这个区别对class的设计影响深远。
侯捷老师的该课程共有13节,本文按课程顺序重新编节。
推荐书籍:
C++ Primer 中英文
Effective C++ 中英文(中文侯捷出品)
Effective Modern C++ 中英文,这个只讲C++2.0
THE C++ STANDARD LIBRARY,STL源码剖析(侯捷出品)
C vs C++ 关于数据与函数
C语言面向过程,数据和函数分开;
C++语言面向对象,数据和处理数据的函数封装成class,class可以实例化多个对象,每个对象有独立的数据部分,而成员函数只有一份,每个对象通过函数指针和this指针共用成员函数。
Object Based vs. Object Oriented
基于对象,面对的是单一class的设计;
面向对象,面对的是多重classes的设计,考量classes之间的关系;
1. 基于对象
1.1 头文件与类的声明
1.1.1 头文件
C++代码基本形式
标准库头文件,#include<> 尖括号;
用户头文件,#include""双引号;
编译器查找顺序,见博文:C++语言;
头文件防卫式声明(declaration)
#ifndef和#pragma,见博文:C++语言;
头文件布局
防卫式声明+标准库头文件+用户头文件+前置声明+类声明+类定义(?)
推荐做法:在头文件声明class,在源文件定义class;–>防止定义多次展开;
1.1.2 类的声明
class template
模板类,用占位符将type的指定延后到实例化对象;
class的声明
有些成员函数在class body中定义;<–自动inline
有些成员函数在class body以外定义,可能是头文件,也可能是源文件;
<–区别?
内联函数
见博文:C++语言;
访问级别
见博文:C++语言;
1.2 构造函数
1.2.1 Big Six
默认构造函数
拷贝构造函数
移动构造函数
拷贝赋值运算符
移动赋值运算符
析构函数
class A {
//=delete, =default;
public:
A() {
...} //构造
A(const A& ) {
...} //拷贝构造
A(A && ) {
...} //移动构造
A& operator=(const A& a) {
...} //拷贝赋值
A& operator=(A&& other) {
...} //移动赋值
~A() {
...} //析构
};
1.2.2 初始化列表
构造函数独有;
初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值操作。
主要是性能问题,对于内置类型,如int, float等,使用初始化类表和在构造函数体内初始化差别不是很大,但是对于类类型来说,最好使用初始化列表,为什么呢?使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,是非常高效的。
1.2.3 构造函数的overloading(重载)
函数名相同,但函数签名不完全相同,则可以构成重载,这些函数同时存在:
- 函数名相同
- 返回值类型不看
- 形参列表个数、顺序、类型有不同
- const
-const在函数尾部,属于函数签名,加const指明不修改入参;
-const在返回值,不看;
-const在传值形参,不看,因为改不改传值没意义;
-const在传引用形参,属于函数签名;
注意与override(覆盖)区分,override是在面向对象角度的类多态中提出的,派生类通过对基类中虚函数覆盖来达到动态绑定的效果。要构成覆盖的条件是:
派生类的函数原型必须完全覆盖基类中的声明,包括:形参列表、返回类型、常量性(cv限定符)。
1.2.4 放在private的构造函数
单例模式,private配合static实现:
class A {
public:
static A& getInstance();
setup() {
...}
private:
A