建议在传递内置类型时,不要使用传址方式;传址机制主要用于传递class object
函数默认参数值只能够指定一次,可以在函数声明处,亦或在函数定义处,但不能够在两个地方点后指定;一般在头文件指定
函数重载:参数列表(参数类型、参数个数)不相同的两个或多个函数,类成员函数是否有const
头文件使用 " " 而非< >
< > 认定为标准的或项目专属的头文件,编译器搜索此文件时,会先在某些默认的磁盘目录中搜寻
" " 认定是一个用户提供的头文件,搜索此文件时,会由要包含此文件的文件所在的磁盘目录开始找起
实现一个find函数,同时支持vector和array
template<typename elemType>
elemType* find(const elemType *first, const elemType *last, const elemType &value) //last 标兵
{
if(!first || !last)
{
return 0;
}
for (; first!=end; first++)
{
if (*first == value)
return first;
}
return 0;
}
缺陷:
vector<string> svec; //为空
find(&svec[0], &svec[svec.size()], search_value); //出错
改进版:
//重写取第一个元素、最后一个元素
template<typename elemType>
inline elemType* begin(const vector<elemType> &vec)
{
return vec.empty() ? 0 : &vec[0];
}
template<typename elemType>
inline elemType* end(const vector<elemType> &vec)
{
return vec.empty() ? 0 : &vec[vec.size()];
}
find(begin(svec), end(svec), search_value);
支持list?
NO。vector、array所有元素存储在连续的空间里,才可以指针++指向下一个元素。
解决方法:
在底层指针的行为之上提供一层抽象。
template<typename IteratorType, typename elemType>
IteratorType find(IteratorType first, IteratorType last, const elemType &value)
{
for (; first != end; first++)
{
if (*first == value)
return first;
}
return last;
}
如果并未提供==运算符,或用户希望赋予==运算符不同的意义?
解决方法:
函数指针、function object ====》将某行为传给函数
vector<int> filter(const vector<int> &vec, int filter_value, bool (*pred)(int, int))
{
vector<int> nvec;
for (int ix = 0; ix < vec.size(); ix++)
if (pred(vec[ix], filter_value))
nvec.push_back(vec[ix]);
return nvec;
}
//pred的一种比较方式
bool less_than(int v1, int v2)
{
return v1 < v2 ? true : false;
}
class Triangular_iterator
{
public:
Triangular_iterator(int index) : _index(index-1){ }
bool operator==(const Triangular_iterator& rhs) const
{
return _index == rhs._index;
}
bool operator!=(const Triangular_iterator& rhs) const
{
return !(*this == rhs);
}
int operator*() const
{
check_integrity();
return Triangle::_elems[_index];
}
Triangular_iterator& operator++() //前置
{
++_index;
check_integrity();
return *this;
}
Triangular_iterator operator++(int ) //后置
{
Triangular_iterator tmp = *this;
++_index;
check_integrity();
return tmp;
}
private:
void check_integrity() const
{
if(_index >= Triangle::_max_elems)
throw iterator_overflow();
if(_index >= Triangle::_elems.size())
Triangular::gen_elements(_index+1);
}
int _index;
};
class Triangle
{
public:
typename Triangular_iterator iterator; //让用户不必知道iterator class的实际名称
Triangular_iterator begin() const
{
return Triangular_iterator(_beg_pos);
}
Triangular_iterator end() const
{
return Triangular_iterator(_beg_pos+_length);
}
friend int Triangular_iterator::operator*();
friend void Triangular_iterator::check_integrity();
private:
int _beg_pos;
int _length;
int _max_elems;
static vector<int> _elems;
};
int main()
{
Triangle tri(20);
Triangle::iterator it = tri.begin();
Triangle::iterator end_it = tri.end();
while (it != end_it)
{
cout<<*it<<' ';
++it;
}
cout<<endl;
}
lt(ival); //lt可能是函数名称、可能是函数指针、可能是一个提供了function call运算符的function object
class LessThan
{
public:
LessThan(int val):_val(val){ }
bool operator( )(int value) const //可以接受任意个数的参数
{
return value < _val;
}
private:
int _val;
};
int count_than(const vector<int> &vec, int comp)
{
LessThan lt(comp);
int count = 0;
for(int ix=0; ix<vec.size(); ++ix)
{
if(lt(vec[ix]))
++count;
}
}
//把function object 当做参数传递给泛型算法
void print_less_than(const vector<int> &vec, int comp, ostream &os=cout)
{
LessThan lt(comp);
vector<int>::const_iterator iter = vec.begin();
vector<int>::const_iterator it_end = vec.end();
while ((iter=find_if(iter, it_end, lt)) != it_end)
{
os<<*iter<<" ";
++iter;
}
}
动态绑定:
找出实际被调用的究竟是哪一个派生类的函数这一解析操作会延迟至运行时(run-time)才进行。
凡基类定义一个(或多个)虚函数,应该将其destructor声明为virtual
类中的Data member如果是个reference,必须在constructor的member initialization list中加以初始化
在基类的constructor(destructor)中调用虚函数,一定会解析为基类自身的那一份虚函数
以初始化列表对类型参数进行初始化,而不选择在函数体内进行
//方式1
template<typename valType>
inline BTnode<valType>::BTnode(const valType &val):_val(val)
{
_cnt = 1;
_lchild = _rchild = 0;
}
//方式2
template<typename valType>
inline BTnode<valType>::BTnode(const valType &val)
{
_val = val;
_cnt = 1;
_lchild = _rchild = 0;
}
将valType指定为内置类型int,
BTnode btni(42);
两种形式效率上没有差异。
BTnode btnm(transform_matrix);
第一种方式只需以copy constructor 将val复制给_val
第二种方式_val赋值操作分为两个步骤;
(1)Matrix的default constructor会先作用于_val
(2)函数体内会以copy assignment operator将val复制给_val
异常处理机制:
1)异常的鉴定与发出
2)异常的处理方式
抛出一个异常 (异常是某种对象)
throw 42;
throw “panic :no buffer”;
重新抛出异常
try
{
}
catch( ... ) //捕获任何异常
{
。。。
throw;
}