C 11学习笔记 13

发布 2022-06-17 16:05:28 阅读 1606

除了重载的函数调用运算符operator()之外,其他重载运算符不能含有默认实参。

当以个重载的运算符是成员函数时,this绑定到左侧运算对象。成员运算符函数的(显式)参数比运算对象的数量少一个。

当运算符作用于内置类型的运算对象时,我们无法改变运算的含义。

这四个运算符不能被重载。

我们只能重载已有的运算符,不能发明新的。优先级和结合律不变。

data1 + data2;

operator+(data1,data2);

上述两个是等价调用。

因为重载运算符其实是函数调用,逻辑与、逻辑或、和逗号的运算对象求值顺序规则无法保留下来,因此,不应该被重载。

还有一个原因是的我们不重载逗号和取址运算符:c++语言已经定义了这两种运算符用于类类型对象时的特殊含义,所以一般不重载,否则它们的行为将异于常态,从而导致类用户无法适应。

赋值运算,左侧运算对象和右侧运算对象的值相等,并且运算符应该返回它左侧运算对象的一个引用。

成员函数还是非成员函数:

赋值(=)下标([ 调用( (和成员访问箭头(->运算符必须是成员函数。

复合运算符一般来说应该是成员,但非必须,只一点与赋值运算略有不同。

改变对象状态的运算符或者与给定类型密切相关的运算符,如递增、递减和解引用运算符,通常应该是成员。

具有对称性的运算符可能转换任意一端的运算对象,例如算术、想等性、关系和位运算符等,因此他们通常应该是普通非成员函数。

如果我们想提供含有类对象的混合型表达式,则运算符必须定义成非成员函数。如int和double相加。

当我们把运算符定义成成员函数时,它的左侧运算对象必须是运算符所属类的一个对象。

输出运算符的第一个参数是一个非常量ostream对象的引用,因为写入内容会改变其状态,是引用因为我们无法直接复制一个ostream对象。

第二个参数一般是一个常量的引用,该常量使我们想要打印的类类型。引用是因为我们希望避免复制实参。常量是不会改变内容。

为了与其他保持一致一般返回ostream形参。

ostream &operator<<(ostream &os , const sales_data &item)

os<<

return os;

输出运算符应该尽量减少格式操作,可以使用户来控制输出细节。不应该打印换行符。

与iostream标准库兼容的输入输出运算符必须是普通的分成员函数。

输入运算符的第一个参数是运算符将要读取的流额引用,第二个参数是将要读入到的( 非常量 )对象的引用,通常会返回某个给定流的引用。

istream &operator>>(istream &is , sales_data &item)

double price;

is >>price;

if(is)

= *price;

elseitem = sales_data( )

return is;

输入运算符必须处理输入可能失败的情况,而输出运算符不需要。

在执行输入运算时可能发生以下错误:

当流含有错误类型的数据时读取操作可能失败。

当读取操作到达文件末尾或者遇到输入流的其他错误是也会失败。

当读取操作发生错误时,输入运算符应该负责从错误中恢复。

虽然我们可以使用failbit,eofbit,badbit等错误标示,但最好是让标准库来标示错误。

算术和关系运算符定义成非成员函数,以允许左右的运算对象进行转换。因为这些运算符一般不需要改变运算对象的状态,所以形参都是常量引用。

如果定义了算术运算符,则一般也会定义一个对应的复合运算符。 符合允许符一般来说应该是成员,但非必须,只一点与赋值运算略有不同。

如果类同时定义了算术运算符合相关的复合赋值运算符,则通常情况下应该使用复合赋值运算符来实现算术运算符。

sales_data operator+(const sales_data &lhs , const sales_data &rhs)

sales_data sum = lhs;

sum +=rhs;

return sum;

bool operator ==const sales_data &lhs, const sales_data &rhs)

return &&

bool operator !=cosnt sales_data &lhs, const sales_data &rhs)

return !(lhs ==rhs);

如果某个类在逻辑上有相等的含义,则应该定义operator ==

特别因为关联容器和一些算法要用到小于运算符,所欲定义operator《会比较有用。

如果存在唯一一种逻辑可靠的《定义,则应该考虑为这个类定义《运算符。如果类同时还包含 ==这当且仅当《的定义和==产生的救国一致是才定义《运算符。

除了拷贝赋值和移动赋值,类还可以定义其他赋值运算符以使用别的类型作为右侧运算对象。例如vector,定义了第三中赋值运算符,元素列表作为参数。

vector v;

v = 为strvec添加这个运算符。

class strvec

const std::string& operator[ ]std::size_t n) const

private:

std::string *elements;

在迭代器类中通常有递增和递减运算符,不必须是成员函数,但因为它们改变的正好是所操作对象的状态,所以建议使用成员函数。

为了与内置版本一致,前置返回的是递增后的对象的引用。后值饭会的是对象的原值,返回的形式是一个值而非引用。

/前置版本。

class strblobptr{

public:

strblobptr& operator++

strblobptr& operator--

strblobptr& strblobptr::operator++(

//如果curr已经指向容器尾后位置,则无法递增它。

check(curr,"increment past end of strblobptr");

++curr;

return *this;

strblobptr& strblobptr::operator--(

//如果curr是0,则继续递减它将产生一个无效下标。

--curr; /如果curr已经是0,那么我们传递个check的值将是一个表示无效下标的非常大的正整数。

check(curr , decrement past begin of strblobptr");

return *this;

为了区分前置和后置版本,后置版本接受一个额外的int类型的形参。只是为了区分前置和后置的函数。

class strblobptr{

public:

strblobptr operator++(int);

strblobptr operator--(int);

strblobptr strblobptr::operator++(

/ 此处无效检查有效性,调用前置递增运算时才需要检查。

strblobptr ret = this;

++*this;

return ret;

strblobptr strblobptr::operator--(int)

strblobptr ret = this;

C11学习笔记 5

参数传递时,如果是引用类型,它将绑定到对应的实参上,否者,将实参的值拷贝后赋给形参。引用可避免拷贝,如果不需要改变参数,最好定义成常量引用。和其他初始化一样,当用实参初始化时会忽略顶层const,当形参有顶层const时,传给它常量对象或非常量对象都可以。我们可以用非常量初始化一个底层const对象...

C 11学习笔记 11

动态分配的内存,只有在显式释放是,这些对象才会销毁。但是标准库中的两智能指针可以确保自动释放。除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间或堆。静态内存用来保存局部static对象 类static数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数没得非stat...

C 11学习笔记 16

tuple是类型pair的模板。不同tuple类型的成员类型也不同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的。当我们希望将一些数据组合成单一对象,但有不想麻烦地定义一个新数据结构来表示时,tuple是非常有用的。快速而随意 的数据结构 tuple类型及其伴随类...