Widget(const Widget& rhs); //copy构造函数
Widget& operator=(const Widget& rhs); //copy assignment
//使用
w1(w2); //copy构造函数
w1 = w2; //copy assignment
Widget w1 = w2; //copy构造函数
//operator=函数体
Bitmap* pOrig = pb; //pb是成员变量
pb = new Bitmap(*rhs.pb); //rhs是参数
delete pOrig
return *this
Widget temp(rhs);
swap(temp);
return *this;
int priority();
void processWidget(std::tr1::shared_ptr pw, int priority);
processWidget(std::tr1::shared_ptr(new Widget), priority);
std::tr1::shared_ptr pw (new Widget);
processWidget(pw, priority());
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
const Rational operator* (const Rational& rhs) const;
}
result = oneHalf*2;
//正确,仅在Rational的构造函数non-explicit下,2被通过构造函数隐式转换为类似于Rational temp(2)
result = 2 * oneHalf;
//错误,2中找不到相应的operator*(),查找non-member函数也找不到正确参数类型的函数
class Rational { ... }
const Rational operator* (const Rational& lhs, const Rational& rhs) { ... }
result = oneForth * 2;
result = 2 * oneForth;
//上述两行代码都正确
namespace std
{
template <typename T>
vois swap(T& a, T& b)
{
T temp(a); a = b; b = temp(a);
}
}
namespace std
{
template<>
void swap(Widget& a, Wiget& b)
{
a.swap(b);
}
}
template void swap>(Widget& a, Widget<&> b)
这种叫偏特化,在模板函数上是不允许的,只允许在模板类中using std::swap
:首先查找T中的,再查找std全特化版,最后使用std的swap()using std::swap;
曝光函数//C风格转型
(T) expression;
//函数风格转型
T( expression );
const_cast( expression )
:唯一有能力的将对象常量性转除dynamic_cast( expression )
:“安全向下转型”决定某对象是否归属继承体系中的某个类型,可能耗费重大运行成本;许多实现版本执行速度相当慢reinterpret_cast( expression )
:意图执行低级转型实际动作可能取决于编译器,不可移植static_cast( expression )
:强迫隐式转换,如将non-const转为constclass Widget
{
explicit Widget(int size);
};
DoSomeWork(Widget(15)); //没错,这是转型而不是创建新对象
DoSomeWork(static_cast(15)); //转型
static_cast(*this).VirtualFunc();
:调用的是父类的函数,但是其操作的是转型建立的*this的base成分暂时副本int doSomething() throw();
//带着“空白的异常明细”函数不一定是nothrow保证函数。而是如果抛出异常是严重错误会有某个意想不到函数调用,用set_unexpected()设置
class Derived: public Base
{
public: //基类中public在public派生类也应该是public
using Base::mf1; //从此父类中mf1()都可见,无论是否重载等
virtual void mf1(); //继承机制仍然有用
}
class Derived: private Base
{
public:
virtual void mf1() //暗自成为inline
{
Base::mf1();
}
}
class Airplane
{
public:
virtual void fly() = 0;
protected:
void defaultFly();
}
class ModelA : public Airplane
{
public:
virtual void fly() //inline调用,有关系吗?
{ defaultFly(); }
}
class GameCharacter
{
public:
int healthValue();
//virtual函数的wrapper/外覆器:做事前事后工作并调用doHealthValue()
private:
virtual int doHealthValue();
}
但是不能访问non-public成员来计算结果,非得这样只能弱化封装:设non-member为friend或提供专门访问函数
int defaultHealthCalc();
class GameCharacter
{
public:
typedef int (*HealthCalcFunc) ();
GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) :
healthFunc(hcf) { }
private:
HealthCalcFunc healthFunc;
}
//将以上代码中typedef改为下边即可
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
//函数对象
struct HealthCalculator
{
int operator() (const GameCharacter&) const
{ }
};
GameCharacter gc( HealthCalculator() ); //使用方法
//使用成员函数时候注意成员函数默认第一个参数为this。可以创建一个对象用bind()绑定来抵消第一个参数
GameLevel currentLevel; //health()式GameLevel中成员函数
GameCharacter gc2(
std::tr1::bind(&GameLevel::health, currentLevel, _1)
);
//需要重新定义virtual使用private继承情况:
//Timer类自动会定时调用public virtual onTick(),因而可以private继承并重写这个函数达到自定义定时功能。如:
class Widget : private Timer //private继承使客户无法调用Timer中的onTick()
{
private: //private是必要的,使客户不误以为这是可调用接口
void void onTick() const; //一些需要定时执行的功能
}
//上述是好设计,但是private继承不是必要的,可用复合替换:
class Widget
{
private:
class WidgetTimer: public Timer
{
public:
virtual void onTick() const;
}
WidgetTimer timer;
}
template<typename T>
void doProcwssing()
{
if (w.size() > 0 && w != soneNastWidget) { }
}
//if的表达式中隐含着T类型要支持size()、operator>等函数接口
//但是由于操作符重载带来的可能性,T类型不一定得支持(比如可以继承自T的基类),而且由于隐式转换等原因使得模板提供了许多的可能
template<typename C>
void print2nd()
{
C::const_iterator * x;
//由于编译器不知道C的内容,从语法上甚至可以理解为C中有个静态变量const_iterator,则该语句理解为其和x的乘积,而不是定义了一个变量x
//C++规则默认嵌套从属名称不是类型,因而其认为const_iterator是一变量
typename C::const_iterator iter(); //正确:用typename明确说明其是类型
}
template<typename T>
class Derived : public Base::Nested //不允许在base class list中
{
explicit Derived(int x) :
Base::Nested(x) //不允许在mem init list中
{
typename Base::Nested tmp; //必须要typename
}
};
//IterT为一个typename IterT模板参数
typedef typename
std::iterator_traits::value_type value_type;
value_type tmp;
//这样减少了重复编码量
//另,traits class的一种运用:如果IterT为vector::iterator则tmp为int型
template<typename Company>
class MsgSender
{
void sendclear();
{
Company c;
c.sendCleartext();
}
//do something
};
class CompanyZ;
//针对CompanyZ全特化
template<>
class MsgSender
{
//do something else completely
};
template<typename Company>
class LoggingMsgSender: public MsgSender
{
void sendClearMsg()
{
//发送前写日志
sendClear(); //调用基类的功能
//发送后写日志
}
}
//代码膨胀经典例子:非类型参数导致
template<typename T, std::size_t n> //n为非类型参数
class SquareMartix { ... };
//将产生两副重复的代码
SquareMartix<double, 5> sm1;
SquareMartix<double, 10> sm2;
template<typename T>
class SmartPtr
{
public:
template<typename U> //刻意不声明为explicit:原始指针转换是隐式的
SmartPtr(const SmartPtr& other) : //member template:为了生成copy构造函数
heldPtr(other.get()) //只有当存在某个隐式转换将U*转为T*时才能通过编译
{ }
T* get() const { return heldPtr; } //返回原始指针
private:
T* heldPtr;
};
template<class T>
class shared_ptr
{
public:
template<class Y>
explicit shared_ptr(Y* p); //构造来自任何兼容的内置指针
template<class Y>
explict shared_ptr(weak_ptr const& r); //explicit:weak_ptr到其shared_ptr的隐式转换不被认可
template<class Y>
shared_ptr& operator+(shared_ptr const& r);
};
//根据条款24的代码改动的代码
template<typename T>
class Rational
{
public:
Rational(const T& numerator = 0, const T& denominator = 1);
//...
};
template<typename T>
const Rational operator* (const Rational& lhs, const Rational& rhs) { } //do something
Rational<int> oneHalf(1, 2);
Rational<int> result = oneHalf * 2; //无法通过编译
friend //在template Rational定义式中
const Rational operator*(const Rational& lhs, const Rational& rhs);
//在class template中template名称可被用来作为template和其参数的简略表达。故上述等价于
friend
const Rational operator*(const Rational& lhs, const Rational& rhs);
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag{};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_iterator_tag : public bidirectional_iterator_tag {};
template<typename IterT, typename DistT>
void advance(IterT iter, DistT d)
{
if (iter is a random access iterator)
{
iter += d; //针对random access迭代器算数运算
}
else
{
//用while 循环++iter或者--iter
}
}
template< ... > //略而未写参数
class deque
{
public:
class iterator
{
public:
typedef random_access_iterator_tag iterator_category;
//...
};
//...
};
//在list中相应语句是:typedef bidirectional_itreator_tag iterator_category;
template<typename IterT>
struct iterator_traits
{
typedef typename IterT::iterator_category iterator_category;
//...
};
//针对指针类型提供一个偏特化版本(parital template specialization)
template<typename IterT>
struct iterator_traits
{
typedef random_access_iterator_tag iterator_category; //指针的行为和random access类似
//...
};
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
if(typeid(typename std::iterator_traits::iterator_category)
== typeid(std::random_access_iterator_tag))
//...
}
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
doAdvance(
iter, d,
typename std::iterator_traits::iterator_category);
}
//重载函数1:针对random access。注意重载函数的第三个形参类型
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::random_access_iterator_tag)
{
iter += d;
}
//重载函数2:针对input iterator。由于forward_iterator_tag是public继承自input_iterator_tag,故该函数也可以处理forward iterator
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::input_iterator_tag)
{
if (d < 0)
throw std::out_of_range("Negative distance");
while(d--)
++iter;
}
template<unsigned n>
strcut Factorial
{
enum { value = n * Factorial1>::value};
};
template<>
struct Factorial<0> //特殊情况:终止条件
{
enum {value = 1};
};
//例如条款44中
typedef SquareMatrix<double, 10000> BigMatrix;
BigMatrix m1, m2, m3, m4, m5;
//...
BigMatrix result = m1 * m2 * m3 * m4 * m5;
//“正常的”函数调用会产生4个临时对象及各自独立的矩阵运算。
//而使用高级、与TMP相关的template技术即expression tmplates,就可能消除临时对象、合并循环,无需改变客户端用法,使用较少内存又有速度提升
//声明于中的标准程序库函数
namespace std
{
typedef void (*new_handler) ();
new_hander set_new_handler(new_handler p) throw(); //表示不抛出异常
}
//使用方法
void outOfMem() { }
std::set_new_handler(outOfMem);
//operator new(不管全局还是类内自定义)的标准形式
void* operator new(std::size_t size);
//来自More Effective C++:
//new operator为系统new关键字不可改变,其中调用opeartor new()进行分配(其返回裸内存,之后调用构造函数进行初始化)。
//用户可以重载opeartor new()自定义分配行为。
class Widget : public NewHandlerSupport { }
//定义于
Widget* p = new (std::nothrow) Widget;
//这行仍然可能异常:new不抛出异常但是Widget构造函数可能调用其他版new仍然抛出异常
//non-member
void operator delete(void* rawMemory) throw();
//member in class
void operator delete(void* rawMemory, std::size_t size) throw();
//C++标准程序库中一个placement new,声明于
//众多placement new中特别有用的一个,是最早的版本
//接受一个指针指向对象该被构造之处;用途之一:在vector未使用空间上创建对象
void* operator new(std::size_t, void* pMemory) throw();
//placement new的使用
Widget* pw = new (pMemory) Widget;
//C++在global作用域提供的operator new
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new(std::size_t, void*) throw();
void* operator new(std::size_t, const std::nothrow&) throw();