第十三、十四章主要讲了复制控制与操作符重载的相关内容。同时也提供了一些例子说明在某些情况下必须使用以及如何使用自定义的复制控制。
复制构造函数是一种特殊的构造函数,它接受该类类型的引用作为其形参。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数,当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式使用复制构造函数。
析构函数是构造函数的互补,当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。
赋值操作符是在左对象已存在的情况下,使用右操作数对左对象进行赋值。
复制构造函数、析构函数和赋值操作符总称为复制控制。
复制构造函数和赋值操作符不一样,复制构造函数是在对象不存在的时候,利用形参创建一个对象;赋值操作符使用的场景是存在一个左对象,对左对象的成员用右操作数进行重新赋值。
#include <iostream>
#include "Query.h"
using namespace std;
int main(){
Query t( "text" );
//此时q不存在,即使使用的是=,调用的也是复制构造函数
Query q = t;
Query p( "string" );
//q已经是一个Query对象了,此时才真正调用赋值操作符
q = p;
}
另外,赋值构造函数常常需要先确定左右操作数不是同一个对象(&rhs != this )
如果类不允许复制,可以将复制构造函数声明为private的,然而,这样做的时候类的友元和成员仍可以进行复制,如果想要连友元和成员中的复制也禁止,可以声明一个private复制构造函数但不对其定义。不允许复制的类对象只能作为引用传递给函数或者从函数返回,它们也不可以用作容器的元素。
重载操作符其实也是一种函数,它可以是类的成员函数,也可以是非成员函数。当作为成员函数时,第一个操作数是this。作为非成员函数时,由于某些操作符会用到类的私有成员(如operator<<),因此可以将其声明为友元。重载操作符必须具有一个类类型操作数。
选择做为成员函数还是非成员函数,有一些指导原则:
1. 赋值(=)、下标([])、调用(())和成员访问(->)必须定义为成员,将这些操作符定义为非成员函数将在编译时标记为错误。
2. 像赋值一样,复合赋值操作符通常应定义为类的成员。
3. 改变对象或与给定类型紧密联系的其他一些操作符,如自增、自减和引引用,通常应定义为成员。
4. 对类的操作符,如算术操作符、相等操作符、关系操作符和位操作符,最好定义为非成员函数。(IO操作符必须为非成员函数)
定义下标操作符比较复杂的地方在于,它在用作赋值的左右操作数时都应该能表现正常。下标操作符出现在左边,必须生成左值,可以指定引用作为返回类型而得到左值。只要下标操作符返回引用,就可用作赋值的任意一方。
可以对const和非const对象使用下标。应用于const对象时,返回值应为const,因此不能用作赋值的目标。
定义下标操作符时,一般要定义两个版本,一个为非const成员并返回引用,一个为const成员并返回const引用。
class Foo{
public:
int& operator[]( const size_t );
const int& operator[]( const size_t) const;
private:
vector<int> data;
};
int& Foo::operator[]( const size_t index ){
return data[index];
}
const int& Foo::operator[]( const size_t index ) const{
return data[index];
}
解引用操作符跟下标操作符一样,必须定义两个版本,一个为const的,一个为非const的。
箭头操作符比较特殊,它表现起来是一个二元操作符,->后面指向一个成员标识符,我们不大可能将成员标识符作为函数的形参进行调用,因此,在解析箭头操作符时,一般分三步。举个例子,point->action()(实际上等价于(point->action)())
(1)如果point是一个指针,指向具有名为action的成员对象的类对象,则编译器将代码编译为调用该对象的action成员。
(2)否则,如果action是定义了operator->操作符的类的一个对象的成员,则point->action与point.operator->()->action相同,即执行point的operator->(),然后使用该结果重复这三步。
(3)否则,代码出错。
自增与自减引用主要必须考虑前缀形式和后缀形式。
这两章中对我来说最重要,也是最陌生的概念,即为函数对象(functional object)。函数对象,就是在某种方式上表现得像函数的对象,典型地,它是指一个类的实例,这个类定义了调用操作符operator()。与函数对象相关的概念是函数适配器,就是之前在STL一章留下的空白。不过我感觉我还没有完全学透函数对象的用法,它在标准库中的使用我也没有完全弄明白,有些函数接口也根本看不出来是要用一个函数还是一个函数对象,又好像看到网上有人说到可以通过模板使得它即能接受函数指针,又能接受函数对象,也许看完第16章的模板,我会有一个更好的理解吧,到时候再专门讲一讲函数对象。
转换操作符是一种特殊的类成员函数,它定义将类类型值转变了其他类型值的转换。如下:
class smallInt{
public:
smallInt( int i=0 ):val(i){
if( i<0 || i>255 )
throw std::out_of_range( "Bad SmallInt initializer" );
}
//转换操作符,从smallInt到int类型的转换
operator int() const{ return val; }
private:
std::size_t val;
};
基本上就是这样了,这两章讲述了复制控制的三个函数,还有一些重载操作符应该注意的事情,包括应该定义为成员还是非成员函数、几种操作符的重载,下标操作符、解引用操作符、箭头操作符、自增自减、调用操作符(与函数对象相关)、转换操作符,最后还提到了转换与重载的关系,以及可能出现的二义性。
分享到:
相关推荐
根据提供的信息,我们可以推断出这是一段与C++编程语言相关的教材内容。尽管原文包含大量乱码,但我们可以从可识别的部分出发,提取并解释关键知识点。 ### 标题和描述中的知识点 #### C++ Premier 第四版中文版 ...
c++ premier 是学习c++的经典著作,通过学习这本数,你可以有很大进步;本资源是书本对应的习题解答,第四版,相当详细
1. **基础语法**:C++的基础语法包括变量、数据类型、运算符、流程控制(如if语句、循环)、函数等。这部分内容是所有编程语言学习的起点,也是理解C++后续特性的基础。 2. **面向对象编程**:C++的核心在于其面向...
《C++ Primer Plus》是一本深受程序员喜爱的C++...总的来说,"CPP-Premier-Plus.zip_plus_销售"包含的资源是C++初学者和教育者的宝贵工具,它们有助于深化理论学习,提高实践能力,并可能推动相关课程的推广与销售。
3. **类与对象**:C++的核心是面向对象编程,类是对象的蓝图,而对象则是类的实例。书中将详细讲解如何定义类,包括成员变量和成员函数,以及构造函数和析构函数的作用。此外,还将探讨访问修饰符(public、private...
总的来说,《2017-NESC-handbook-premier-edition.pdf》是电力行业的重要参考资料,它不仅提供了全面的安全规定,还为实际操作提供了详细指导,对于理解和执行电气安全标准至关重要。无论是专业人员还是行业新手,都...
通过阅读和运行这些代码,读者可以更直观地理解C++的各种特性,如类的设计与实现、模板的使用、异常处理、输入输出流等。同时,这些源代码也展示了良好的编程习惯和风格,对于培养编程思维和提升代码质量有着积极的...
Premier - MS Windows Shell Script Programming for the Absolute Beginner.chm
《Premier - Crystal Reports 9 Essentials》是一本深入解析Crystal Reports 9这一强大报表工具的教程,旨在帮助用户掌握其核心功能与应用技巧。Crystal Reports是Business Objects公司(现为SAP的一部分)开发的一...
oracle ebs
XMind是一个非常神奇的软件,能够帮助我们组织思考,很不错的工具。C++ Premier是非常成熟的开发语言讲解书籍,非常经典
总理眼物体检测程序 开始工作之前,Premier-eye需要在设备上创建数据和输出文件夹,并将图像放置在此处以进行识别工作。物体检测模块当地使用要求: Python> = 3.6 对于运行模块,您需要运行API和SPA来发送数据,...
附件的内容为使用思维导图XMind总结C++标准库的顺序容器,通过把C++ Premier顺序容器翔实的放在一张图片上,可以非常方便的梳理思路,在工作中也能提高工作效率。灵活的使用容器是C++开发人员必须具备的技能
使用XMind学习C++Premier.好好学习好好工作aaaaaaaaa阿凡达附加库撒地方就是扩大了房价数据奥凯电缆飞机撒看到