C++ primer plus读书笔记——第11章 使用类

第11章 使用类

1. 运算符重载是一种形式的C++多态。

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

3. 运算符重载的格式如下:

operatorop(argument-list);

可以使用函数表示法或运算符表示法来使用它。

total = coding + fixing;

total = coding.operator+(fixing);

4. 运算符重载的限制:

1)  重载后的运算符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载运算符。

2)  使用运算符时不能违法运算符原来的句法规则。例如,操作数个数不能变,不能修改运算符的优先级。

3)  不能创建新运算符。例如,不能定义operaor**()函数来求幂。

4)  不能重载下面的运算符。

sizeof

.(成员运算符)

.*(成员指针运算符)

::

?:

typeid(一个RTTI运算符)

const_cast强制类型转换运算符

dynamic_cast强制类型转换运算符

reinterpret_cast强制类型转换运算符

static_cast强制类型转换运算符

5)  大多数的运算符可以通过成员或非成员函数的进行重载,但下面的运算符只能通过成员函数进行重载。

=赋值运算符

()函数运算符

[]下标运算符

->通过指针访问类成员的运算符

5. 友元有三种:

友元函数

友元类

友元成员函数

  1. 6.  友元函数虽然是在类中声明的,但它不是类的成员函数,因此不能使用成员运算符来调用。友元函数虽然不是类的成员函数,但它与成员函数的访问权限相同。

7. 创建友元

1)  将原型放在类声明中,并在原型声明前加上关键字friend

friend Time operator*(double m, const Time & t);

2)  编写函数定义。因为它不是成员函数,所以不要使用Time::限定符。另外,不要在定义中使用关键字friend。

Time operator*(double m, const Time &t)

{

}

8. 只有类声明可以决定哪一个函数是友元,因此类声明仍然控制了哪些函数可以访问私有数据。总之,类方法和友元只是表达类接口的两种不同机制。

9. 类继承属性使得ostream引用能够指向ostream对象和ofstream对象。

10. 一般来说,要重载<<运算符来显示c_name的对象,可使用一个友元函数,其声明如下:

friend ostream & operator<<(ostream & os, const c_name & obj);

11. 重载运算符:作为成员函数还是友元函数(非成员函数)

对于某些运算符来说,成员函数是唯一合法的选择。在其他情况下,这两种格式没有太大的区别。有时,根据类设计,使用非成员函数版本可能更好(尤其是为类定义类型转换时)。

12. 想返回一个自定义的类对象时,可以返回一个其构造函数。用构造函数来生成一个新对象,可以避免麻烦。

13. 友元函数如果是在类声明中进行定义,尽管没有inline关键字,但将是一个内联友元函数。

14. 随机数

头文件cstdlib(stdlib.h)包含了srand()和rand()的原型,而ctime(time.h)包含了time()的原型。C++使用头文件random中的函数提供了更强大的随机数支持。

15. 在C++中,接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图,而且支持隐式转换。

Stonewt(double lbs);

Stonewt myCat;

myCat = 19.6;

只有接受一个参数的构造函数才能作为转换函数。下面的构造函数有两个参数,因此不能用来转换。

Stonewt(int stn, double lbs);

然而,如果第二个参数提供默认值,它便可以用来转换int:

Stonewt(int stn, double lbs = 10);

16. 编译器在什么时候使用Stonewt(double)函数进行隐式类型转换呢?

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

2)  将double值赋值给Stonewt对象时。

3)  将double值传递给接受Stonewt参数的函数时。

4)  返回值被声明为Stonewt的函数试图返回double值时。

5)  在上述任意一种情况,使用可转换为double类型的内置类型时

Stonewt Jumbo(7000);

Jumboo = 7300;

17. 隐式类型转换有时会带来意外的灾难,C++新增了关键字explicit用来关闭这种特性。

explicit Stonewt(double lbs);

这将关闭上述示例中的隐式转换,当仍然允许显示转换。

Stonewt myCat;

myCat = 19.6; //not valid

myCat = Stonewt(19.6);// ok

myCat = (Stonewt)19.6;// ok

18. 转换函数

构造函数只用于从某种类型到类类型的转换。要进行相反的转换,必须使用转换函数。P415

定义转换函数后,既可以使用强制转换,也可以让编译器自动进行隐式转换。

Stone wolfe(285.7);

double host = double(wolfe);

double thinker = (double)wolfe;

double star = wolfe;

要转换为typeName类型,需要使用这种形式的转换函数:

  • operator typeName();

请注意以下几点:

1)  转换函数必须是类方法;

2)  转换函数不能指定返回类型(typeName已经给出了);

3)  转换函数不能有参数(已经隐式提供了);

例如,转换为double类型的原型如下:operator double();

19. 应该谨慎地使用隐式转换函数。原则上说,最好使用显式转换函数,避免隐式转换函数。在C++98中,关键字explicit不能用于转换函数,但C++11消除了这种限制。因此,在C++11中,可将转换运算符声明为显式的。

例如:

explicit operator int() const;

时间: 2024-10-14 05:38:03

C++ primer plus读书笔记——第11章 使用类的相关文章

C++ primer plus读书笔记——第16章 string类和标准模板库

第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string & str, size_type pos = 0, size_type n = pos)初始化为str中从pos开始到结尾的字符,或从pos开始的n个字符 string(const char *s, size_type n)初始化为s指向的前n个字符,即使超过了s的结尾: string(Iter b

《浪潮之巅》读书笔记——第11章 摩托罗拉

第11章 摩托罗拉  公司发展    1928创立 原名高尔文制造公司    基因      注重技术和品质    1947 改名摩托罗拉    2011 拆分为摩托罗拉移动和摩托罗拉解决方案两个独立上市公司    2011 Google收购摩托罗拉移动 获得大量专利 扭转了苹果和微软的专利战  产品    最早是做汽车收音机 Motorola是其品牌    给军方做便携式无线通信工具 步话机二战前    模拟无线通信的老大(无线双工霸主)    1946 汽车电话    1958 汽车对讲机 

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

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

C++ primer plus读书笔记——第14章 C++中的代码重用

第14章 C++中的代码重用 1. 使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现).获得接口是is-a关系的组成部分.而使用组合,类可以获得实现,但不能获得接口.不继承接口是has-a关系的组成部分. 2. C++还有另一种实现has-a关系的途径——私有继承.使用私有继承,基类的公有成员和保护成员都将称为派生类的私有成员.这意味着基类方法将不会称为派生类对象公有接口的一部分,但可以在派生类的成员函数中使用它们. 3. 包含将对象作为一个命名的成员对象添加到

C++ primer plus读书笔记——第1章 预备知识

第1章 预备知识 1. Ritchie希望有一种语言能将低级语言的效率.硬件访问能力和高级语言的通用性.可移植性融合在一起,于是他在旧语言的基础上开发了C语言. 2. 在C++获得一定程度的成功后,Stroustrup才添加了模版,这使得进行泛型编程成为可能. 3. Linux中要支持C++11,编译源文件时要使用-std = c++0x选项: g++ -std = c++0x use_auto.cpp 4. 程序执行完毕后,有些IDE自动关闭窗口,而有些IDE不关闭.为查看输出,可以在程序的最

C++ primer plus读书笔记——第9章 内存模型和名称空间

第9章 内存模型和名称空间 1. 头文件常包含的内容: 函数原型. 使用#define或const定义的符号常量. 结构声明. 类声明. 模板声明. 内联函数. 2. 如果文件名被包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统中查找.但如果头文件名包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录(或其他目录,这取决于编译器).如果没有在那里找到头文件,则将在标准位置中查找.因此在包含自己的头文件时,应使用引号而不是尖括号. 3. 链接程序将目标文件代码.库代码和

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

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

C++ primer plus读书笔记——第8章 函数探幽

第8章 函数探幽 1. 对于内联函数,编译器将使用相应的函数代码替换函数调用,程序无需跳到一个位置执行代码,再调回来.因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存. 2. 要使用内联函数,需要在: 函数声明前加上关键字inline; 函数定义前加上关键字inline; 3. 程序员请求将函数作为内联函数时,编译器不一定会满足这种需求.它可能认为该函数过大或注意到函数调用了自己(内联函数不能递归). 4. 必须在声明引用变量时进行初始化 int rat = 101; int &

C++ primer plus读书笔记——第7章 函数——C++的编程模块

第7章 函数——C++的编程模块 1. 函数的返回类型不能是数组,但可以是其他任何一种类型,甚至可以是结构和对象.有趣的是,C++函数不能直接返回数组,但可以将数组作为结构或对象的组成部分来返回. 2. 在C++中括号为空意味着不指出参数.在ANSI C中,括号为空意味着不指出参数.在C++中,不指定参数列表时应该用省略号. void say_bye(…); 3.  数组名数组名解释为其第一个元素的地址有一些例外,首先,对数组名使用sizeof将得到整个数组的长度:其次,将地址运算符用于数组名时