本周開始進(jìn)入C++面向?qū)ο蟾呒?jí)編程(下)的課程中
內(nèi)容好散,寫得累死。
1. Conversion Function,轉(zhuǎn)換函數(shù)
在類需要轉(zhuǎn)換成為其它類型時(shí),需要設(shè)計(jì)轉(zhuǎn)換函數(shù)
函數(shù)簽名一般格式為:operator typename() const
,無參數(shù),不用顯式寫出返回類型。
例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; // 調(diào)用operator double()將 f 轉(zhuǎn)為 0.6
2.non-explicit-one-argument ctor
注:未加explicit
修飾的單參數(shù)構(gòu)造函數(shù),如 例2 中Fraction
類的構(gòu)造函數(shù)。
例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; // 調(diào)用non-explicit ctor將 4 轉(zhuǎn)換為 Fraction(4, 1)
// 然后調(diào)用operator+
!! conversion function vs. non-explicit-one-argument ctor
下面是兩種函數(shù)并存所導(dǎo)致的錯(cuò)誤情況,當(dāng)有多條路線可以達(dá)到目的時(shí),將導(dǎo)致歧義。
例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
關(guān)鍵字后,one-argument ctor將不能自動(dòng)轉(zhuǎn)換。
例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. 關(guān)于智能指針
智能指針的一般形式如下:
例5:
template <typename T>
class shared_ptr
{
public:
T& operator *() const
{
return *px;
}
T& operator ->() const
{
return px;
}
private:
T* px;
long* pn;
……
};
!! 箭頭運(yùn)算符->
是一種特殊的運(yùn)算符,它將一直向下作用,不會(huì)被消耗。
2. 關(guān)于迭代器
針對(duì)容器設(shè)計(jì)對(duì)應(yīng)的迭代器。
例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,所謂仿函數(shù)
指重載了函數(shù)調(diào)用運(yùn)算符()
的類,使用時(shí)可以像調(diào)用函數(shù)一樣。
例7:
template <typename T>
struct identity
{
const T& operator()(const T& x) const { return x }
};
6. class template,類模版
將可變?cè)刈龀赡0妫褂迷撃0鏁r(shí)再與具體的類型進(jìn)行綁定。
例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,函數(shù)模版
又稱算法。
例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); // 編譯器會(huì)對(duì)function template進(jìn)行實(shí)參推導(dǎo)(argument deduction)
8. menber template,成員模版
類內(nèi)也可以設(shè)置成員模版。
例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,模版(全)特化
針對(duì)泛化編程中的某些情況可以設(shè)計(jì)特殊的算法,稱為模版特化。
例11:
template <typename Key>
struct hash {};
template <>
struct hash<char>
{
size_t operator ()(char x) const { return x; }
}
10. partial specialization,模版偏特化
1. 個(gè)數(shù)的偏
例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,模版模版參數(shù)
將模版作為模版參數(shù)時(shí)使用。此時(shí)默認(rèn)模版參數(shù)必須顯式寫出。
例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; // 錯(cuò)誤
XCls<string, Lst> mylst2;
12. Reference
Reference底層是利用指針實(shí)現(xiàn)的。(漂亮的指針)
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聲明,前提對(duì)象賦予默認(rèn)值。
例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;
}