[GeekBand][C++面向对象高级编程]第四周学习笔记

2017-02-11  本文已影响0人  散夜霜

本周开始进入C++面向对象高级编程(下)的课程中
内容好散,写得累死。

1. Conversion Function,转换函数

在类需要转换成为其它类型时,需要设计转换函数
函数签名一般格式为:operator typename() const,无参数,不用显式写出返回类型。

例1:
class Fraction
{
public:
    Fraction(int num, int den = 1)
        :m_numerator(num), m_denominator(den) {}
    operator double()   const
    {
        return double(m_numerator) / double(m_denominator);
    }

private:
    int m_numerator;
    int m_denominator;
};
Fraction f(3, 5);
double d = 4 + f;   // 调用operator double()将 f 转为 0.6

2.non-explicit-one-argument ctor

注:未加explicit修饰的单参数构造函数,如 例2 中Fraction类的构造函数。

例2:
class Fraction
{
public:
    Fraction(int num, int den = 1)
        :m_numerator(num), m_denominator(den) {}
    Fraction operator+(const Fraction& f)
    {
        return Fraction(……);
    }

private:
    int m_numerator;
    int m_denominator;
};
Fraction f(3, 5);
double d2 = f + 4;  // 调用non-explicit ctor将 4 转换为 Fraction(4, 1)
                    // 然后调用operator+

!! conversion function vs. non-explicit-one-argument ctor

下面是两种函数并存所导致的错误情况,当有多条路线可以达到目的时,将导致歧义

例3:
class Fraction
{
public:
    Fraction(int num, int den = 1)
        :m_numerator(num), m_denominator(den) {}
    operator double()   const
    {
        return double(m_numerator) / double(m_denominator);
    }
    Fraction operator+(const Fraction& f)
    {
        return Fraction(……);
    }

private:
    int m_numerator;
    int m_denominator;
};
Fraction f(3, 5);
Fraction d2 = f + 4;    // [Error]ambiguous

3. explicit-one-argument ctor

explicit关键字后,one-argument ctor将不能自动转换。

例4:
class Fraction
{
public:
    explicit Fraction(int num, int den = 1)
        :m_numerator(num), m_denominator(den) {}
    operator double()   const
    {
        return double(m_numerator) / double(m_denominator);
    }
    Fraction operator+(const Fraction& f)
    {
        return Fraction(……);
    }

private:
    int m_numerator;
    int m_denominator;
};
Fraction f(3, 5);
Fraction d2 = f + 4;    // [Error]conversion from 'double' to 'Fraction' requested

4. pointer-like classes

1. 关于智能指针

智能指针的一般形式如下:

例5:
template <typename T>

class shared_ptr
{
public:
    T& operator *() const
    {
        return *px;
    }

    T& operator ->() const
    {
        return px;
    }

private:
    T* px;
    long* pn;
……
};
!! 箭头运算符->是一种特殊的运算符,它将一直向下作用,不会被消耗。
2. 关于迭代器

针对容器设计对应的迭代器。

例6:
template <typename T>
struct __list_node
{
    void* prev;
    void* next;
    T data;
};
template <typename T,typename Ref,typename Ptr>
struct __list_iterator
{
    typedef __list_iterator<T, Ref, Ptr> self;
    typedef Ptr pointer;
    typedef Ref reference;
    typedef __list_node<T>* link_type;
    link_type node;
    bool operator==(const self& x) const { return node == x.node; }
    bool operator!=(const self& x) const { return node != x.node; }
    reference operator*() const { return (*node).data; }
    pointer operator->() const { return &(operator*()); }
    self& operator++() { node = link_type((*node).next); return *this; }
    self operator++(int) { self tmp = *this; ++*this; return tmp; }
    self& operator--() { node = link_type((*node).prev); return *this; }
    self operator--(int) { self tmp = *this; --*this; return tmp; }
};

5. function-like classes,所谓仿函数

指重载了函数调用运算符()的类,使用时可以像调用函数一样。

例7:
template <typename T>
struct identity
{
    const T& operator()(const T& x) const { return x }
};

6. class template,类模版

将可变元素做成模版,使用该模版时再与具体的类型进行绑定。

例8:
template <typename T>
class complex
{
public:
    complex(T r = 0, T i = 0)
        :re(r), im(i)
    {}
    complex& operator +=(const complex&);
    T real() const { return re; }
    T imag() const { return im; }
private:
    T re, im;
    friend complex& __doapl(complex*, const complex&);
};
{
    complex<double> c1(2.5, 1.5);
    complex<int> c2(2, 6);
    ……
}

7. function template,函数模版

又称算法

例9:
template <typename T>
inline const T& min(const T& a, const T& b)
{
    return a < b ? b : a;
}
class stone
{
public:
    stone(int w, int h, int we)
        :_w(w), _h(h), _weight(we)
    {}
    bool operator <(const stone& rhs) const
    {
        return _weight < rhs._weight;
    }
private:
    int _w, _h, _weight;
};
stone r1(2, 3), r2(3, 3), r3;
r3 = min(r1, r2);   // 编译器会对function template进行实参推导(argument deduction)

8. menber template,成员模版

类内也可以设置成员模版。

例10:
template <typename T1, typename T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;

    pair()
        :first(T1()), second(T2())
    {}
    pair(const T1& a, const T2& b)
        :first(a), second(b)
    {}

    template <typename U1, typename U2>
    pair(const pair<U1, U2>& p)
        : first(p.first), second(p.second)
    {}
};

9. (full) specialization,模版(全)特化

针对泛化编程中的某些情况可以设计特殊的算法,称为模版特化。

例11:
template <typename Key>
struct hash {};
template <>
struct hash<char>
{
    size_t operator ()(char x) const { return x; }
}

10. partial specialization,模版偏特化

1. 个数的偏

例12:
template <typename T, typename Alloc=……>
class vector
{
    …
};
template <typename Alloc = ……>
class vector<bool, Alloc>
{
    …
};

2. 范围的偏

例13:
template <typename T>
class C
{
    …
};
template <typename T>
class C<T*>
{
    …
};
C<string> obj1;
C<string*> obj2;

11. template template parameter,模版模版参数

将模版作为模版参数时使用。此时默认模版参数必须显式写出。

例14:
template <typename T, template <typename T>class Container>
class XCls
{
private:
    Container<T> c;
public:
    ……
};
template <typename T>
using Lst = list<T, allocator<T>>;
XCls<string, list> mylst1;  // 错误
XCls<string, Lst> mylst2;

12. Reference

Reference底层是利用指针实现的。(漂亮的指针)

13. variadic templates (since C++11)

拆包用,直接上例子。

例15:
void print()
{
}

template <typename T,typename... Types>
void print(const T& firstArg, const Types&... args)
{
    cout << firstArg << endl;
    print(args...);
}

14. auto (since C++11)

可以将auto作为typename声明,前提对象赋予默认值。

例16:

auto a = 0; // a是int

15. ranged-base for (since C++11)

格式如下

for (delc : coll)
{
    statement;
}
例17:
vector<double> vec;
…
for (auto elem : vec)
{
    cout << elem << endl;
}

for (auto& elem : vec)
{
    elem *= 3;
}
上一篇下一篇

猜你喜欢

热点阅读