本周开始进入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;
}
网友评论