《C++ Primer Plus》读书笔记之九—使用类

第十一章 使用类

  1、操作符函数的格式:operator op(argument-list)。op是将要重载的操作符。

  2、操作符重载函数的两种调用方式:①函数表示法:C=A.operator+(B);A、B、C都是类对;②操作符表示法:C=A+ B;操作符左侧的对象A是调用对象,操作符右边的对象B是作为参数被传递的对象。

  3、不要返回指向局部变量或临时对象的引用,函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据。

  4、C++对用户定义的操作符重载的限制:①重载的操作符不必是成员函数,但必须至少有一个操作数是用户定义的类型。这将防止用户为标准类型重载操作符。②使用操作符时不能违反操作符原来的句法规则,不能修改操作符的优先级。③不能定义新的操作符。④不能重载下面的操作符:(sizeof)、(.)、(.*)、(::)、(?:)、typeid、const_cast、dynamic_cast、reiniterpret_cast、static_cast。⑤下面的操作符只能通过成员函数进行重载:(=赋值操作符)、(()函数调用操作符)、([]下标操作符)、(->)。

  5、注意:重载的成员函数操作符,左侧的操作数是调用对象。

  6、非成员函数,不是由对象调用的,它使用的所有值(包括类对象)都是显式参数。但是,如果函数对类对象有所操作,非成员函数不能直接访问类的私有成员。这时候,需要一类特殊的函数——友元函数。

  7、友元函数:将原型放在类声明中,并在原型声明前加上关键字friend:①友元函数不是成员函数,因此不能使用成员操作符来调用。②虽然友元函数不是成员函数,但它与成员函数的访问权限相同。注意:编写友元函数定义时,不要使用类作用域限定符(classname::),不要在定义中使用关键字friend。

  8、如果要为类重载操作符,并将非类的项作为第一个操作数,则可以用友元函数来反转操作数的顺序,因为第一个操作数必须为类对象。

  9、cout是一个ostream对象,它是智能的,能够识别所有的C++基本类型。这是因为对于每种基本类型,ostream类声明中都包含了相应的重载的operator<<()定义。

  10、如果想要用cout输出一个类对象的值,可以通过在类中声明一个友元函数来重载operator<<()函数,如下:

  ostream & operator<< (ostream & os,const Time & t)

  {

    os<<t.hours<<t.minutes;

    return os;

  }

  那么,Time trip;cout<<trip;被转化成operator<<(cout,trip);

  11、对于很多操作符来说,可以选择使用成员函数或非成员函数来实现操作符重载。一般来说,非成员函数应是友元函数,这样它才能直接访问私有数据。

  12、记住:非成员版本的重载操作符函数所需的形参数目与操作符使用的操作数目相同;而成员版本所需的参数数目少一个,因为其中的一个操作数是通过this指针被隐式的传递的调用对象。

  13、对于两个Time类对象T2、T3,求T1=T2+T3;可以用两种格式实现,如下。但要注意:不能同时选择这两种格式,因为这两种格式都与同一个表达式匹配,同时定义这两种格式将被视为二义性错误,导致编译错误。

  T1=T2.operator+(T3);  // 成员函数

  T1=operator+(T2,T3); // 非成员函数(友元)

  14、因为操作符是通过函数是实现的,所以只要操作符函数的特征标相同,使用的操作符数量与相应的内置C++操作符相同,就可以多次重载同一个操作符。

  15、将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接收变量的类型。 C++语言不自动转换不兼容的类型(例如:int *p=10;非法,不过可以强制类型转换:int *p=(int*)10;)。

  16、C++允许指定在类和基本类型之间进行转换的方式。首先,任何接受唯一一个参数的构造函数都可被用作转换函数,将类型与该参数相同的值转换为类。如果将类型与该参数相同的值赋给对象,则C++将自动调用该构造函数。例如:有类Stonewt,则Stonewt mycat;mycat=19.6;程序将使用构造函数Stonewt(double)来创建一个临时的Stonewt对象,并将19.6作为初始值。随后,采用逐成员赋值方式将该临时对象的内容复制到mycat中。这一过程称为隐式转换。不过,如果该构造函数的声明前加上了关键字explicit,则该构造函数不能用于这种隐式转换,只能用于显式转换:mycat=Stonewt(19.6);

  17、何时使用Stonewt(double)进行隐式转换呢?

  ①将Stonewt对象初始化为double值时。

  ②将double值赋给Stonewt对象时。

  ③将double值传递给接受Stonewt参数时。

  ④返回值被声明为Stonewt的函数试图返回一个double值时。

  ⑤在上述任一种情况下,使用可转换为double类型的内置类型时(先将内置类型转换成double,再调用构造函数)。

  18、Stonewt mycat=19.6等价于:①Stonewt mycat(19.6);②Stonewt mycat=Stonewt(19.6);不过后两种格式可用于接受多个参数的构造函数。

  19、构造函数只用于从某种类型到类类型的转化,要进行相反的转换(即将类转换成某种类型),必须使用特殊的C++操作符函数——转换函数。转换函数是用户定义的强制类型转换。

  20、对于转换函数,注意以下几点:①转换函数必须是类方法。②转换函数不能指定返回类型。③转换函数不能有参数。具体的格式为:

operator typename();例如转换为double类型的函数原型为:operator double();注:转换函数是类方法意味着:它需要通过类对象来调用,从而告知函数要转换的值。因此,函数不需要参数。

  21、转换函数的隐式转换:double mycat1=mycat;如果只定义了double转换函数,因此不存在二义性,但是如果定义了int和double两个转换函数operator double();和operator int();则该语句long mycat2=mycat;有二义性而被拒绝!因为int和double值都能赋给long值,所以编译器认为使用任意一个转换函数都是合法的。但是如果删除了其中一个,编译器将接受该语句。

  22、当类定义了两种或多种的转换时,仍可以用显式强制类型转换来指出使用哪个转换函数:long mycat2=(double)mycat;或者long mycat2=int(mycat);

  23、实现加法时的选择:比如要将double量(或者其他内置类型)和Stonewt (类对象)量相加,有两种选择:

  ①将operator + (const Stonewt&,const Stonewt&)定义为友元函数,让Stonewt(double)构造函数将double类型的参数转换为Stonewt类型的参数。

  ②将加法操作符重载为一个显式使用double类型参数的函数:Ⅰ、Stonewt operator +(double X);//成员函数  Ⅱ 、friend Stonewt operator+(double X,Stonewt & s); // 友元函数

  优缺点:第一种方法依赖于隐式转换,使程序更简短,因为定义的函数较少。缺点是每次转换时,都将调用转换构造函数,增加时间和内存开销。第二种方法(增加一个显式的匹配类型的函数)则刚好相反。它使程序更长,但运行速度较快。

原文地址:https://www.cnblogs.com/smile233/p/8874836.html

时间: 2025-01-01 08:37:57

《C++ Primer Plus》读书笔记之九—使用类的相关文章

C++ primer plus读书笔记——第13章 类继承

第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生出新的类.而且可以在不公开实现的情况下将自己的类分发给其他人,同时允许他们在类中添加新特性. 2. 派生类构造函数首先创建基类对象,如果不调用基类构造函数,程序将使用默认的基类构造函数. 3. 创建派生类对象时,程序首先调用基类构造函数,然后再调用派生类构造函数.派生类对象过期时,程序将首先调用派生

C++ primer plus读书笔记——第12章 类和动态内存分配

第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化. P426-P427类静态成员的声明和初始化 //strnbad.h class StringBad { private: static int num_strings; … }; //strnbad.cpp int StringBad::num_strings = 0; 不能在类声明中初始化静态

C++primer读书笔记9转换与类类型

有时候指定了自己类类型来表示某种类型数据如SmallInt,那么为了方便计算就会指定一个转换操作符,将该类类型在某种情况下自动的转换为指定的类型 <1>转换操作符 operator type(); 转换函数必须是类成员函数,不能指定返回类型,并且形参列表必须为空,并且通常不应该改变转换对象,所以操作符通常定义为const成员. #include <iostream> using namespace std; class SmallInt { public: SmallInt(int

C++ Primer 3rd 读书笔记

C++ Primer 3rd 读书笔记1/2 分类: C/C++/VC2014-04-08 20:43 318人阅读 评论(0) 收藏 举报 第一章    开始 1.       C++中标准的头文件是不带.h后缀的.如下代码值得注意: #include <iostream.h> void sayHello() { cout<<"Hello World!"; } void main() { sayHello(); } #include <iostream&

Hadoop读书笔记(九)MapReduce计数器

Hadoop读书笔记系列文章:http://blog.csdn.net/caicongyang/article/category/2166855 1.MapReduce 计数器的作用 统计Map.Reduce以及Combiner执行的次数,可以用户简单判断代码的执行流程 2.MapReduce自带的计数器 14/11/26 22:28:51 INFO mapred.JobClient: Counters: 19 14/11/26 22:28:51 INFO mapred.JobClient: F

《C++ Primer》读书笔记—第十三章 控制拷贝

声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程 第III部分,类设计者的工具 1.类是C++的核心概念.每个类都定义了一个新类型和在此类型对象上可执行的操作. 2.当定义一个类时,我们显式或隐式地指定在此类型的对象的拷贝.移动.赋值和销毁时做什么.一个类通过定义五种特殊的成员函数来控制这些操作,包括:拷贝构造函数(copy construcor),拷贝赋值运算符(copy-assignment operato

《C++ Primer》读书笔记—第一章 开始

声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.一个函数的定义包含四个部分:返回类型(return type).函数名(function name).一个括号包围的形参列表(parameter list,允许为空)以及函数体(function body). 2.cin.cout的使用 1 #include<iostream> 2 int main() 3 { 4 std::cout <

《C++ Primer》读书笔记—第十六章 模板与泛型编程

---恢复内容开始--- 声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程 1.面向对象编程和泛型编程都是处理在编写程序时不知道类型的情况,不同之处在于,OOP能处理类型在程序运行之前都未知的情况,而在泛型编程中,在编译时就能获知类型了. 2.泛型编程与面向对象编程一样,都依赖于某种形式的多态性.面向对象编程中的多态性在运行时应用于存在继承关系的类. 3.在泛型编程中,我们所编写的类和函数能够多态地用于跨越编译

《C++ Primer》读书笔记—第四章 表达式

声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程 1.表达式由一个或多个运算对象组成,对表达式求值将得到一个结果.字面值和变量是最简单的表达式,其结果就是字面值和变量的值.把一个运算符和一个或多个运算对象组合起来可以生成复杂的表达式. 2.指针不能转换成浮点数. 3.一个左值表达式的求职结果是一个对象或者一个函数,然而以常量对象为代表的某些左值实际上不能作为赋值语句的左侧运算对象. 4.在除法运算中,如果两个运