美文网首页
[GeekBand][C++面向对象高级编程(下)]第四周笔记

[GeekBand][C++面向对象高级编程(下)]第四周笔记

作者: readME_boy | 来源:发表于2017-08-10 23:27 被阅读0次

    第四周内容比较的散,大纲如下

    1. Conversion Function
    2. non-explicit one argument constructor
    3. pointer-like classes
    4. Function-like classes
    5. namespace经验谈
    6. class template
    7. Function Template
    8. Member Template
    9. specialization
    10. 模板偏特化
    11. 模板模板参数
    12. 关于C++标准库
    13. 三个主题
    14. Reference
    15. 复合&继承关系下的构造和析构

    第四周的内容也是相对零零散散,有虚函数指针vptr,虚函数表vtbl的,有this指针,有动态绑定Dynamic Binding。后边还讲到了成员函数。能写多少写多少吧。

    1. Conversion Function
    Operator 类型名(){转换语句}
    

    比如这个例子:

    #include<iostream>
    using namespace std;
    class Fraction
    {
    public:
        Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
        operator double( ) const 
        { 
            cout<<"operator double( ) is called!!!"<<endl;
            return (double)(m_numerator / m_denominator); 
        }
    private:
        int m_numerator; //分子
        int m_denominator; //分母
    };
    
    int main( )
    {
        Fraction f(3, 5);
        double d = 4+f;   //调用operator double( ) 将f 转换为0.6.
        return 0;
    }
    
    

    转换函数在函数名前面不能指定函数类型,函数也没有参数,至于是否要加const,根据转换后的结果来判定,一般都会加上const。在使用过程中,不必显示地调用类型转换函数,它往往是自动被调用的,即隐式调用。

    23转换构造函数:一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数)。

    它有两个作用:一是构造器,二是默认且隐式的类型转换操作符。

    1. 关键字explicit:

    Explicit用于防止隐式转换的,普通的构造函数能过被隐式调用,而explicit构造函数只能被显示调用。

    non-explicit-one-argument ctor 可隐式转换单一形参构造函数形如:

    #include<iostream>
    using namespace std;
    class Fraction
    {
    public:
        Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den)
        { 
            cout<<"non-explicit ctor is called!!!"<<endl;
        }
        Fraction operator + (const Fraction &f)  
        { 
            cout<<"operator +(...) is called!!!"<<endl;
            return Fraction(this->m_numerator+f.m_numerator, this->m_denominator+f.m_denominator);
        }
    
        int getNumerator() const {return m_numerator;}
        int getDenominator() const {return m_denominator;}
    
    private:
        int m_numerator;    //分子
        int m_denominator;  //分母
    };
    
    ostream& operator<<(ostream &os, const Fraction &f)//重载<<运算符
    {
        return os<<"分子: "<<f.getNumerator()<<"分母: "<<f.getDenominator();
    }
    
    int main( )
    {
        Fraction f(3, 5);        //调用non-explicit ctor
        Fraction d2 = f+4;       //调用non-explicit ctor将4转为 Fraction(4,1)
                                 //然后调用operator + 
        cout<<d2<<endl;          //因为引用传递,所以会再调用一次non-explicit ctor
        return 0;
    }
    
    
    1. shared_ptr是一种智能指针(smart point),它会记录有多少个shared_ptr共享一个对象。当最后一个指向对象的指针被销毁,这个对象就会被自动删除。
    **shared_ptr<int> sp(new int(10));                //一个指向整数的shared_ptr    
    assert(sp.unique());                            //现在shared_ptr是指针的唯一持有者     
    shared_ptr<int> sp2 = sp;                       //第二个shared_ptr,拷贝构造函数     
    assert(sp == sp2 && sp.use_count() == 2);       //两个shared_ptr相等,指向同一个对象,引用计数为2    
    *sp2 = 100;                                     //使用解引用操作符修改被指对象    
    assert(*sp == 100);                             //另一个shared_ptr也同时被修改     
    sp.reset();                                     //停止shared_ptr的使用    
    assert(!sp);                                    //sp不再持有任何指针(空指针) 
    **
    

    网上的例子。

    1. 迭代器(iterator)

    迭代器提供对一个容器中的对象的访问方法,并定义了容器中对象的范围。迭代器就如同一个指针。

    1. typename
      这周课侯老师讲了在泛型编程中typename和class具体有无区别。侯老师也讲了,在模板声明里是完全没用区别的。侯老师也提到了在模板里面的使用是有些微的区别的。但是限于篇幅与时间的限制,侯老师并没有深入讨论,所以在本笔记中,我们会讨论typename与class的区别。
      比如我们有一个模板函数,该函数可以打印容器内的所有元素。如下图所示,即使没有typename,函数也能运行。

    可是,如果我们写一个自己的容器类,不但有const_iterator这一迭代器类型,还有一个静态变量也叫const_iterator。这时候编译器就会会出现解析错误了。因为我们知道,静变量可以通过使用类名::变量名调用的。所以T::const_iterator不但是一个类型名还是一个变量名,这时候就要加入typename了。

    1. 范围for语句

    C++11新引入了一种更简单的for语句,用于遍历容器或其它序列的所有元素。

    语法结构:

    for(declaration : expression){
    
             ……
    
    }
    

    expression为要遍历的容器

    declaration为变量类型,用于存放容器中的元素,若是不清楚容器中的元素类型,可以使用auto类型说明符。

    例如:

    vector<int> v={0,1,2,3,4,5,6,7,8,9};
    
    for(auto r:v)
    
    {
    
             cout<<r<<endl;
    
    }
    

    在上面的代码中提到了auto,它是类型说明符。

    在编程时,常常需要把表达是的值赋值给变量,这就要求在声明变量的时候清楚地知道表达式的类型,然而,往往做不到这一点,所以引入了auto类型说明符,它让编译器通过初始值来推算变量的类型。所以,auto定义的变量一定要有初始值。

    6.[GeekBand][C++面向对象高级编程(下)]第四周作业
    作业解答在这里

    相关文章

      网友评论

          本文标题:[GeekBand][C++面向对象高级编程(下)]第四周笔记

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