美文网首页
侯捷 视频 上

侯捷 视频 上

作者: my_passion | 来源:发表于2020-06-08 23:13 被阅读0次

    1 C++简介

    OOP: Object Oriented Programming 
        面向对象: 是一种思想
    
    procedural language: 过程式语言
    

    1.1 class 设计

    小代码 & 良好的 c++ 编程习惯
    
    1   Object Based
    
        基于对象: 单一 class 
    
            2种 经典 class 分类:
                class with / without pointer members: String / Complex
    
    2   Object Oriented
    
        面向对象: 多个class, 主要考虑 class 间关系
    
            继承  inheritance
            组合  composition
            委托  delegation
    

    1.2 C++ 演化

        new C -> C with class -> C++: 1983
    
        C++98(1.0) -> C++11(2.0)
    

    1.3 相比于 C, C++ 更注重 标准库

        C: 主要关注 语言层面
    
        C++: C++ 语言 &  C++ 标准库
    

    1.4 好书

        1   语言部分
    
            全世界最畅销的2本
    
                << C++ Primer >> C++ 第1个编译器作者
    
                << The C++ Programming Language >> C++之父 Bjarne Stroustrup
    
        2   专家经验
    
            << Effective C++>>
    
        3   标准库
    
            << The C++ Standard Liarbry >>
    
            << STL 源码剖析 >>
    
            STL: Standard Template Library, 是 标准库的前身 
    

    2 class 声明

    2.1 C++ 与 C: ptr 和 func 不同

        C:
            数据: 具有 类型/type (build-in, struct)
                据 类型 create 出 Variables
    
            函数: 处理 variables
    
        C++:
            wrap ptr 和 ( 处理 ptr 的 ) func, 形成 class
    
            以 class 为 type create 出 objects
    
            C++ 的 class 源于 C 的 struct, 又加入了新特性
            
            ptr/对象 可能有 多份/多个, 处理对象的 `函数 只有1份`
    

    2.2 C++ ptr 与 func

        1   Complex
    
            ptr:      实部 虚部
            
            Functions:  
    
                
    
        2   String
        
            ptr: ptr — 指向1个 字符串
    
            functions: copy 等
    

    2.3 C++ 代码

        .h/hpp: 标准库
        .h    : class Declaration
        .cpp: include<> + include " "
    

    2.4 C++ / C: 输出

    C++: 不需要 告诉编译器 要输出的变量 类型

        //c++
        int i = 5;
        cout << i << endl;
    
        //c
        printf("%d\n", i);
    

    2.5 头文件 & 防卫式声明

    程序 中 第1次 include 头文件 时, 
        由于 未曾定义过  _COMPLEX_  这个 name, 所以定义它; 
        然后进入 头文件 body. 
    
    第2次 include 头文件 时, 
        由于 已定义过 _COMPLEX_ , 所以 不会进入 头文件 body
    
    // complex.h
    #ifndef _COMPLEX_
    #define _COMPLEX_
    ...
    #endif
    

    2.6 头文件布局

        // A.h
        #ifndef _A_
        #define _A_
    
        // (1) 前置声明
        class B;
    
        // (2) class 声明
        class A
        {
            // class body 内  直接定义 的 函数
        };
    
        // (3) class body 外 定义 的 函数
        A::function ...
    
        #endif
    

    3 构造函数

    1   class 声明
    
        class complex
        {         // class body
            friend complex& _doapl (complex*, const complex&);
        public:
            complex (double r = 0, double i = 0) // 1. default arg
                : re (r), im (i)  // 2. initialization list 初始化列表, 只有 ctor 享有这种语法
            { }
    
            complex& operator+=(const complex&); 
            
            double real () const { return re; }
            double imag () const { return im; }
        private:
            double re, im;
        };
    
    2   inline func
    
        inline 好处: 非函数调用
    
        函数 `建议` 编译器 把自己做成 inline(候选人) 的 2种情形:
    
        (1) class body 内 定义 => `自动成为 inline 候选人`
    
        (2) class body 外 explicitly 声明为 inline
    
    3   ctor
    
        可 overload
    
            (1) 在 编译器 看来, 重载函数 不同名
    
            (2) 二义性 -> 编译器 不知道 调哪个 -> 编译 error
    
                complex (double r = 0, double i = 0) 
                    : re (r), im (i) { }
                    
                complex () : re(0), im(0) {}; 
    

    4 参数传递 与 返回值

    1 ctor 放 private => class 称为 Singleton 单例

    (1) class 只在 内部 构造 1份 自己的 static obj, 供 外部 使用

    (2) 不允许外界 创建 object

        class A
        {
        public:
            static A& getInstance();
            setup(){ /* */ }
        private:
            A();
            A(const A& rhs);
        };
    
        A& A::getInstance()
        {
            static A a;
            return a;
        }
    
        // 调用 A::getInstance().setup();
    

    2 const member func: 不改 mem ptr

    const obj 调 non-const mem func => compiler 报错

        `const 对象: 告诉 编译器, 不能改 mem ptr`
        `non-const mem func: 允许改 mem ptr`
    
        class 
        {    
        public:
            double complex::real () const { return re; }
        };
    

    3 参数传递: pass by value vs. pass by reference (to const)

    能传引用 就 传引用

    (1) 引用
        [1] 本质上 也是 指针, 传引用 像 传指针 一样快
    
        [2] 必须 绑定到 已有对象
    

    (2) 指针: 可以是 动态内存的地址 => 此时 必须用指针, 不能用引用

    (3) 何时 不 pass by reference:

    1) iterator

        : cheap-to-copy, pass by value 比 by const reference 更高 效
            reference 本质是 指针
            而 iterator 不过是指针的一种抽象
    

    2) local obj

    (4) 编译器 如何看待 操作符?

    `二元操作符:` 
        编译器 把 操作符 作用在 左边
        若 左边 重载了该操作符
            把 操作符 编译成 调用 相应的 重载函数
    
        ostream&
        operator << (ostream& os, const complex& x)
        {
            return os << '(' << real(x) << ',' << imag(x) << ')';
        }
    
        // 编译器 找 << 的 matched 重载版本: 
        // 对 non-memFunc 而言, << 左操作数 cout 匹配 operator << () 的 para1: ostream& os
        cout << c(2, 1) << endl;
    

    4 返回值传递: return by value / return by reference (to const)

    能传引用 就 传引用

    5 友元 / friend

    (1) 直接访问 friend 的 private 成员: 通过 pointer / reference / obj => 打破封装

    (2) note: 同一 class 各 objects 互为友元

        // (1)
        inline complex&
        _doapl (complex* ths, const complex& c)
        {
            ths->re += c.re;  
            ths->im += c.im;
            return *ths;
        }
        
        // (2) 同一 class 各 objects 互为友元 ( c.re )
        class complex
        {
        public:
            ...
            int fun(const complex& c)
            {
                return c.re + c.im;
            }
            ...
        };
    
        {
            complex c1(2, 1);
            complex c2;
            
            c2.fun(c1);
        }
    

    6 class body 外 定义

        class body 之外 的 函数: 
            用 类名限定 的是 mem func; 否则是 global func
    
        inline complex&
        _doapl (complex* ths, const complex& c) 
        {   //第 1/2 参数 会/不会 被改变
            ths->re += c.re;  
            ths->im += c.im;
            return *ths;
        }
    
        inline complex&
        complex::operator += (const complex& c)
        {
            return _doapl(this, c);
        }
    

    5 操作符重载

    1 mem func with this (implicit para: point to the obj calling the mem func)

    func 中 某段 处理 提取成单独的函数, 以 实现 复用

        complex c1(2, 1);
        complex c2(5);
    
        c2 += c1; 
    
        inline complex&
        complex :: operator += (const complex& c)
        {
            //2. 右边 加到 左边 的这种动作 是一个通用动作,可以单独成函数,供其他 函数调用
            return _doapl(this, c);
        }
    
        inline complex&
        _doapl (complex* ths, const complex& c) //第1参数 会被改变,第2参数不会被改变
        {
            ths->re += c.re;  
            ths->im += c.im;
            return *ths;
        }
    

    2 non-mem func without this

        对某个 操作符重载, 
        只能 写为 `mem func 或 non-mem func` 之一, 
        但两者 `不能同时存在`
    
    // 支持  c1 += c2;
    inline complex
    operator += (const complex& x, const complex& y)
    {
        return complex( real(x) + real(y), imag(x) + imag(y) );
    }
    
    // 支持  c1 += 5;
    inline complex
    operator += (const complex& x, double y)
    {
        return complex( real(x) + y, imag(x) );
    }
    

    3 temp object

    不能 return by reference: 生命到下一行语句就结束了

        inline complex
        operator += (const complex& x, const complex& y)
        {
            return complex( real(x) + real(y), 
                            imag(x) + imag(y) );
        }
    

    4 return by reference

    发端 无需知道 收端 是以 什么形式 接收: 收端 以 value / reference 接收, 发端 都是同一形式 发送

    vs. return by pointer: 发端 必须知道 传的是 pointer => 以 pointer 收, 必须以 pointer 发

        // Note: 返回引用:以 [1] 支持 c3 += c2 += c1 [2] 加完之后更新 左值
        inline complex&
        _doapl (complex* ths, const complex& c)
        {
            ...
            return *ths;
        }
    
        complex::operator += (const complex& c)
        {
            return _doapl(this, c);
        }
    

    6 复习 Complex 类 的实现

    // 1    防卫式 声明 
    #ifndef _COMPLEX_
    #define _COMPLEX_
    
    #endif
    
    // 2    class name
    class complex
    {
    
    };
    
    // 3    mem ptr
    class complex
    {
    private:
        double re, im;
    };
    
    // 4    ctor
    class complex
    {
    public:
        complex (double r = 0, double i = 0)
            : re (r), im (i) {  }
    private:
        double re, im;
    };
    
    // 5    interface func
    // 不改变 mem ptr 的 mem func: 写为 const mem func
    // friend func:
    class complex
    {
        friend complex& _doapl (complex*, const complex&);
    public:
        complex (double r = 0, double i = 0)
            : re (r), im (i) { }
    
        complex& operator += (const complex& );
        double real () const { return re; }
        double imag () const { return im; }
    
    private:
        double re, im;
    };
    

    6 class body 外 operator+= 定义

    1) 设计 func 的 interface
    
        [1] func name
        
            complex::operator+=
    
        [2] para
        
            1> mem func => 只需要 右边
            2> 先考虑 传 reference
            3> 右边加到左边, 右边不动 => const 引用
                complex::operator+=(const complex& c)
    
        [3] return type
        
            1> 得 左边这种 type
            
            2> `return` 的 不是 函数内部创建的 local/temp obj,
                而是 `已经存在的对象 (如 left operand obj)` 时, 
                => 可以传 reference
    
            complex&
            complex::operator+=(const complex& c)
    
        [4] 函数 body 之外 => 建议 为 inline
    
            inline complex&
            complex::operator+=(const complex& c)
    
    2) 设计 func 的 definition
    
        [1] 右边 加到 左边 是 通用动作,
            可   抽取出 作 commonFunc
    
        Note: 把 本 func 要做的事情 丢给 另一 func,
            本 func 与 另一 func: 
                1] return type 相同, 
                2] 相同参数部分 type 相同
    
        [2] 把 this 当 arg 传给 `commonFunc`
    
            inline complex&
            complex::operator+=(const complex& c)
            {
    
                return _doapl(this, c);
            }
    
        [3] 第1参数 会被改变,第2参数 不会被改变(=> const)
    
            inline complex&
            _doapl (complex* ths, const complex& c) 
            {
                ths->re += c.re;  
                ths->im += c.im;
                return *ths;
            }
    
    7   加
    
        加 可以 是 复数 加 复数, 复数 加 实数 等, 
            
            => 写成 non-mem func 更好
    
    8   输出
    
        cout << c1; 
    
        (1) 往 os 里 写时, os 状态 改变 
            => os non-const reference
    
        (2) 输出的 对象 状态不变 => const reference
    
        (3) 对象 cout/os 类型为 ostream
    
        operator << (ostream& os, 
                      const complex& x)
    
        (4)为 支持 cout << obj1 << endl; 
            => cout << obj1 应 return cout 的类型 ostream
    
        (5) cout 不是函数的 local 对象, 而是 本来就有的  
            
            => 可以 return reference
    
            ostream&
            operator << (ostream& os, const complex& x)
            {
    
            }
    
        (6) 按用户想要的方式输出
    
        ostream&
        operator << (ostream& os, const complex& x)
        {
            return os << '(' << real(x) << ',' << imag(x) << ')';
        }
    

    7 带 pointer 的类 — copy control: copy ctor / copy assignment / dtor

    (1) class 带 pointer men, 多半是要 `动态内存分配`
        => 对象 生命结束前, dtor 被调用, 
            必须在 dtor 中 释放 动态分配的内存
    

    (2) class with pointer members 必须有 copy ctor 和 copy op=

    (3) 若无 自我赋值, 则
    左 / 右 pointer ( this->ptr / rhs.ptr) 指向 同一块内存,
    delete[] 左 ponter 后, 该 内存释放,
    再 strcpy(this->ptr, rhs.ptr) 会产生 undefined behavior

    (4) 让 字符串 里 拥有 一个 poiner, 需要 内存时, 才去创建 另一空间 来放 字符串本身

        因为 字符串 内容 有大有小, 这种设计 最好, 
        而不是在 字符串里 放一个 array
    
        String s1();  // ctor,未 指定初值 
        String s2("hello"); // ctor
    
        String s3(s1);  // copy ctor
        cout << s3 << endl;
    
        s3 = s2; // copy assignment
        cout << s3 << endl;
    
        class Stirng
        {
        private:
            char* ptr;
        public:
            String(const char* cstr = 0); // ctor
    
            // copy ctor/assignment: 接收的是 自己这种东西 
            // => para 为 const String&
            String(const String& str);    
            String& operator = (const String& str);
            ~String();
    
            char* get_c_str() const { return ptr; }
        };
    
        // copy ctor 
        inline
        String::String(const char* cstr = 0)
        {
            if(cstr)
            {
                ptr = new char[strlen(cstr) + 1];
                strcpy(ptr, cstr);
            }
            else  // 未 指定初值  eg: String s1();
            {
                ptr = new char[1];
                *ptr = '\0';
            }
        }
    
        inline
        String:: ~String()
        {
            delete[] ptr;
        }
    
        // operator =
        inline 
        String& String::operator = (const String& str)
        {
            if(&str == this) // 检测自我赋值
                return *this;
            
            delete[] ptr;
            ptr = new char[ strlen(str.ptr) + 1];
            strcpy(ptr, str.ptr);
            
            return *this;
        }
    
    1.jpg

    8 堆 栈 内存管理

    8.1 object 生命期

        1   栈 Stack
    
            `某 scope 内`  memory space
    
        2   堆 Heap
    
            `OS 提供 global memory space`
    
                通常以 new/delete 分配/释放
    
    
            `内存泄漏 : 只 分配 不 释放`
    
                ptr 离开 scope 之后就消亡了, 但 ptr 所指 memory 还在`
    
        3   stack object
    
            `dtor 会 自动被调用 => 会被 自动 清理`
    
            scope   : 其所在的 scope
            lifetime: 其所在的 scope
        
        4   static local objects
    
            scope   : 其所在的 scope
            lifetime: 持续到 整个程序结束 
    
            {
                static Complex c2(1, 2);
            }
    
        5   global objects
    
            scope   : 持续到 整个程序结束 
            lifetime: 持续到 整个程序结束 
    
        6 heap objects
        
            scope   : 
            lifetime: 被 delete 时结束
    

    8.2 new / delete / new [] / delete []

    9 String 类 实现过程

    (1) copy ctor
    
        蓝本 是 自身 type 的 obj, 改变了 目的端 ptr 
            => 不能是 const func
    
    (2) copy assignment
        1) 目的端 本来就存在 => return reference
        2) 改变了 目的端 ptr => 不能是 const func
    
    (3) C风格字符串
        return pointer to 字符串
    
        char* get_c_str() const { return ptr; } 
    

    第10讲 class/function template

    第11讲 虚函数 与 多态

    https://www.jianshu.com/p/eb69e02766e7

    第12讲 组合 与 继承

    https://www.jianshu.com/p/0f209eb83f47

    第13将 委托

    https://www.jianshu.com/p/0f209eb83f47

    1. Comopsite - 设计模式
    
    2. Prototype - 设计模式
    

    相关文章

      网友评论

          本文标题:侯捷 视频 上

          本文链接:https://www.haomeiwen.com/subject/yexjtktx.html