std::size_t:位于命名空间std,无符号类型
STL是C++标准程序库的一部分
参数:lhs,rhs
C++:组成;
C
面向对象的C++
TEMPLATE C++
STL 容器,迭代器,算法,函数对象的实现
const ,enum,inline代替#define
const int pi=3.14;
类中:不能使用define
staticconst int num=5;
intsocres[num];
或者
enum{num=5}; 取地址不合法
intsocres[num];
宏使用define可能误用
#define CALL_WITH_MAX(a,b)f((a)>(b)?(a):(b))
int a=5,b=0;
CALL_WITH_MAX(++a,b);a被加1次
CALL_WITH_MAX(++a,b+10);加2次
建议:
纯常量,以const或enums替代#define
类似函数的宏,改用inline函数代替define
尽可能使用const
void f1(const widget* pw)
void f1(widget const * pw)等价
const 成员函数不可以更改对象内任何非static成员变量
除非加上mutable(const函数内可以修改成员变量了)
const ,非const成员函数中避免重复的方法:
非const调用const版本避免代码重复
例如:
const char &operator[](std::size_tposition)const
{
.....
...
...
return text[position];
}
char&operator[](std::size_t position)
{
.....
...
...
return
const_cast<char &>(static_cast<const text&>(*this));
}
\\
对象初始化和赋值的区别:
初始化列表----初始化
:thename(name),theaddress(address)
{}
但--构造函数体内使用赋值
{
the name=name;
theaddress=address;赋值,不是初始化
}
empty e1;默认构造函数
empty e2(e1);拷贝构造函数
e2=e1;赋值操作符
析构函数
不想使用编译器自动生成的函数,就应该明确拒绝
方法一:继承自:privateuncopyable
方法二:成员函数声明为private,并且不实现
多态基类声明virtual析构函数
作用:避免资源泄漏
一个对象经由基类指针,被删除是,基类需要虚析构函数
使用场合:一般类有一个虚函数,才声明虚析构函数
纯虚函数:声明,不实现
抽象类不能定义对象,仅仅引用&,指针*
必须为纯虚析构函数提供定义:因为派生后,每一个基类的析构函数都要被调用。
什么时候定义虚析构函数?
带多态性质的基类/带有虚函数:定义虚析构函数
但:若基类不是为了多态用途或不用做基类,不需要虚析
构函数;
例如:string STL容器不用做基类,
C++并没有禁止析构函数吐出异常
不吐出异常的原因?
因为:过早结束程序或未定义行为
建议;析构函数不抛出异常。若析构函数调用的函数可能发生异常,让析构函数捕捉异常,吞下异常或结束程序
因为:基类构造期间虚函数不会下降到派生类层次,即在基类构造期间,虚函数不是虚函数
基类的构造函数执行早于派生类的构造函数,
当基类构造函数执行时派生类的成员变量未初始化。
此时调用的虚函数不会下降到派生类层次。(取用未初始化的成分是危险的)
更根本的原因:派生类对象的基类构造期间,对象的类型是基类
此时虚函数,运行期类型信息,例如dynamic_cast,typeid,都把对象当成基类
同理,适用于析构函数。一旦派生类析构函数开始执行,对象内的派生类成员变量呈现未定义,
办法:构造函数,析构函数不调用虚函数;
或者派生类构造函数中把参数传递给基类构造函数
注意两点:
(1) x=y=z=15; 必须返回引用
(2) 返回*this
例如
widget& operator =(int rhs)
{
...
return *this;
}
class widget{};
widget w;
w=w;
实现:
方法一:
复制pb所指的东西前别删除pb;
widget&
widget:;operator=(const widget& rhs)
{
bitmap *porig=pb; 不是最高效的 复件,删除原来的,指向新的
pb=new bitmap(*rhs.pb);
delete porig;
return *this;
}
方法二:copy and swap
class widget{
void swap(widget&rhs);
};
widget&widget::operator(constwidget&rhs)
{
widget temp(rhs):
swap(temp):
return *this;
}
或者传递值 多了副本
widget&widget::operator(const widgetrhs)
{
swap(rhs):
return *this;
}
其他不异常安全的实现:
widget&
widget:;operator=(const widget& rhs)
{
delete pb; 不异常安全
pb=new bitmap(*rhs.pb);
return *this;
}
自我赋值检测
widget&
widget:;operator=(const widget& rhs)
{
if(this==&rhs) return *this;
delete pb; 不异常安全
pb=new bitmap(*rhs.pb);//可能产生异常
return *this;
}
实现构造函数时—若初始化列表中实现----- 调用基类的拷贝构造函数
若构造函数体体实现----------调用基类的赋值函数
拷贝构造函数+赋值操作符可以消除重复---二者调用公共的函数
不要使用拷贝构造函数调用赋值操作符