第十四章
重载操作符与转换
1.不能被重载的操作符
::(域)、.*(取指针成员对应的内容)、.(取成员操作符)、?:
2.一般将算数和关系操作符定义成非成员函数,将复制操作符定义为成员函数。
3.输出操作符重载
ostream & operator<<(ostream & os,const ClassType & object)
{
...
}
4.输入操作符重载
istream & operator >> (istream & is,ClassType & object)
{
...
}
注意处理错误和文件结束的可能性
5.赋值操作符
Sales_item & Sales_item::operator +=(const Sales_item & rhs)
6.
//解引用操作符
Screen & operator *() {return *ptr->sp;}
//成员访问操作符
Screen * operator->() {return prt->sp;}
//类定义
class ScreenPtr{
public:
Screen & operator *(){return *ptr->sp;}
Screen * operator ->(){return ptr->sp;}
private:
ScrPtr * ptr;
};
class ScrPtr{
friend class ScreenPtr;
screen *sp;
~ScrPtr(){delete sp;}
};
7. 自增或自减操作符
前置:返回引用
CheckedPtr & CheckedPtr::operator ++()
{
if(curr=end)
throw out_of_range("increment past the end of CheckedPtr!");
++curr;
return *this;
}
后置
CheckedPtr CheckedPtr::operator ++(int)
{
CheckedPtr ret(*this);
++*this;
return ret;
}
8.调用操作符()和函数对象
A
struct absInt{
int operator()(int val){
return val<0?-val:val;
}
};
e.g.
int i =-42;
absInt absobj;
unsigned int ui = absobj(i);
B
absInt定义的absobj被称为函数对象,可以当做函数使用
C
更灵活的调用
class GT_cls{
public:
GT_cls(sizet val = 0):bound(val){}
bool operator()(const string & s)
{
return s.size>=bound;
}
private:
std::string::size_type bound;
};
count_if(word.begin(),word.end(),GT_cls(7));//构造一个函数对象作为标准
D
标准库对应函数对象
plus<int> intAdd;
int sum = intAdd(0,20);
E
bind1st/bind2nd(fun(),10)//将第1/2个操作数绑定为10
not1/not2(fun())//第1/2个操作数取反
9.转换
A
class SmallInt{
operator int() const{return val;}
};
SmallInt可以当做int处理,内置转换。
B
自定义类型->内置类型1->内置类型2 //正确
自定义类型1->自定义类型2->内置类型 //错误,无法自动转换
C
注意构造函数,转换转换操作符引起的二义性。
第十五章 面向对象编程
1.面向对象编程
封装/抽象;继承;多态/动态绑定
2.访问权限:
A 同一类对象a/b可以相互访问彼此任意成员
B 派生类对象a只能对自己基类 protected成员可以访问,对基类对象b的protected成员不可以访问
3.虚函数必须与基类定义方式完全匹配,例外:返回基类型引用或者指针的虚函数
4.用作基类的类必须是已定义的,及时声明了也不行
5.强制使用基类虚函数:
baseP->Item_base::net_price(42);
6.虚函数中默认实参在编译时确定,用基类指针实参为基类,派生类指针实参为派生类。
7.class Derived:private Base{
public:
using Bse::size;//本来是private,转换为public
};
8.友元关系与继承无关
9.无论基类派生多少派生类,每个static成员只有一个实例
10.一个类只能初始化直接基类
11.派生类复值操作符
Derived & Derived::operator=(const Derived & rhs){
if(this!=&rhs){
Base::operator=(rhs);
//...
}
return this;
}
12.
析构函数为虚函数时用基类指针指向派生类然后删除指针,依然运行派生类析构函数。
构造函数在对象构造之前运行,动态类型不完整,不能定义成虚函数。
13.在派生类作用于中派生类成员将屏蔽基类成员。
14.纯虚函数:
double net_price(std::size_t)=0;
包含纯虚函数的类是抽象基类,不能创建对象。
15.句柄类
存储和管理基类指针。
class Sales_item{
public:
Sales_item():p(0),use(new std::size_t(1)){}
Sales_item(const Item_base &);
Sales_item(const Sales_item & i):p(i.p),use(i.use){++*use;}
~Sales_item{decr_use();}
Sales_item & operator=(const Sales_item);
const Item_base *operator->()const
{
if(p)
return p;
else
ERROR;
}
const Item_base & operator*()const
{
if(p)
return *p;
else
ERROR;
}
};
1.不能被重载的操作符
::(域)、.*(取指针成员对应的内容)、.(取成员操作符)、?:
2.一般将算数和关系操作符定义成非成员函数,将复制操作符定义为成员函数。
3.输出操作符重载
ostream & operator<<(ostream & os,const ClassType & object)
{
...
}
4.输入操作符重载
istream & operator >> (istream & is,ClassType & object)
{
...
}
注意处理错误和文件结束的可能性
5.赋值操作符
Sales_item & Sales_item::operator +=(const Sales_item & rhs)
6.
//解引用操作符
Screen & operator *() {return *ptr->sp;}
//成员访问操作符
Screen * operator->() {return prt->sp;}
//类定义
class ScreenPtr{
public:
Screen & operator *(){return *ptr->sp;}
Screen * operator ->(){return ptr->sp;}
private:
ScrPtr * ptr;
};
class ScrPtr{
friend class ScreenPtr;
screen *sp;
~ScrPtr(){delete sp;}
};
7. 自增或自减操作符
前置:返回引用
CheckedPtr & CheckedPtr::operator ++()
{
if(curr=end)
throw out_of_range("increment past the end of CheckedPtr!");
++curr;
return *this;
}
后置
CheckedPtr CheckedPtr::operator ++(int)
{
CheckedPtr ret(*this);
++*this;
return ret;
}
8.调用操作符()和函数对象
A
struct absInt{
int operator()(int val){
return val<0?-val:val;
}
};
e.g.
int i =-42;
absInt absobj;
unsigned int ui = absobj(i);
B
absInt定义的absobj被称为函数对象,可以当做函数使用
C
更灵活的调用
class GT_cls{
public:
GT_cls(sizet val = 0):bound(val){}
bool operator()(const string & s)
{
return s.size>=bound;
}
private:
std::string::size_type bound;
};
count_if(word.begin(),word.end(),GT_cls(7));//构造一个函数对象作为标准
D
标准库对应函数对象
plus<int> intAdd;
int sum = intAdd(0,20);
E
bind1st/bind2nd(fun(),10)//将第1/2个操作数绑定为10
not1/not2(fun())//第1/2个操作数取反
9.转换
A
class SmallInt{
operator int() const{return val;}
};
SmallInt可以当做int处理,内置转换。
B
自定义类型->内置类型1->内置类型2 //正确
自定义类型1->自定义类型2->内置类型 //错误,无法自动转换
C
注意构造函数,转换转换操作符引起的二义性。
第十五章 面向对象编程
1.面向对象编程
封装/抽象;继承;多态/动态绑定
2.访问权限:
A 同一类对象a/b可以相互访问彼此任意成员
B 派生类对象a只能对自己基类 protected成员可以访问,对基类对象b的protected成员不可以访问
3.虚函数必须与基类定义方式完全匹配,例外:返回基类型引用或者指针的虚函数
4.用作基类的类必须是已定义的,及时声明了也不行
5.强制使用基类虚函数:
baseP->Item_base::net_price(42);
6.虚函数中默认实参在编译时确定,用基类指针实参为基类,派生类指针实参为派生类。
7.class Derived:private Base{
public:
using Bse::size;//本来是private,转换为public
};
8.友元关系与继承无关
9.无论基类派生多少派生类,每个static成员只有一个实例
10.一个类只能初始化直接基类
11.派生类复值操作符
Derived & Derived::operator=(const Derived & rhs){
if(this!=&rhs){
Base::operator=(rhs);
//...
}
return this;
}
12.
析构函数为虚函数时用基类指针指向派生类然后删除指针,依然运行派生类析构函数。
构造函数在对象构造之前运行,动态类型不完整,不能定义成虚函数。
13.在派生类作用于中派生类成员将屏蔽基类成员。
14.纯虚函数:
double net_price(std::size_t)=0;
包含纯虚函数的类是抽象基类,不能创建对象。
15.句柄类
存储和管理基类指针。
class Sales_item{
public:
Sales_item():p(0),use(new std::size_t(1)){}
Sales_item(const Item_base &);
Sales_item(const Sales_item & i):p(i.p),use(i.use){++*use;}
~Sales_item{decr_use();}
Sales_item & operator=(const Sales_item);
const Item_base *operator->()const
{
if(p)
return p;
else
ERROR;
}
const Item_base & operator*()const
{
if(p)
return *p;
else
ERROR;
}
};