Effective C++ --经验条款

高效C++ -4

必须返回对象时,别妄想返回其reference:

这句话什么意思呢?就是在一个函数内,如果你需要这个函数返回一个新的对象,那么这个函数的返回值类型就不要定义成引用类型。就直接返回这个类类型。

首先,我们知道在函数传递参数时,传递引用的好处,尤其是对那么比较大的类型,但是对于内建类型和STL的迭代器类型就没有必要使用引用传递,就可以使用值传递。因为对于内建类型传递引用不值得。

下面看一个例子,为何在必须返回对象时,就别想返回对象的引用。因为得到了函数传递引用的好处,有人可能在返回值时也想返回引用。

比如一个Rational(实数类)类,重载了操作符*,然会一个新的对象。

Const Rational& operator*(constRational& lhs,const Rational& rhs)

{

Rationalresult(lhs.n*rhs.n,lhs.d*rhs.d);

Return result;

}

然会一个引用,一个局部变量的引用,在函数结束以后,这个result就消失了,他是在栈空间内的,返回这个是不合适的?

那么这个时候就想着在堆空间中申请空间,然后返回。

Const Rational& operator*(constRational& lhs,const Rational& rhs)

{

Rational* result = new Rational(lhs.n*rhs.n,lhs.d*rhs.d);

Return   *result;

}

这更不合适,在这个函数内申请一段空间,并对这段空间进行初始化然后返回。但是这段空间谁去释放呢?如果是在复杂应用中,更加复杂,这是更不应该的行为。

那么,可能想到了返回staic变量,还是不是很好,以为staic变量谁去调用都是同一个。

其实,到最后,如果一个函数必须返回一个对象,那么就直接返回对象就好了,这是很好的做法。

Inline const Rational operator*(constRational& lhs,const Rational& rhs)

{

ReturnRationl(lhs.n*rhs.n,lsh.d*rhs.d);

}

但是对于重载操作符operator=则要求一定返回 reference *this

Virtual函数系动态绑定而来,意思是调用一个virtual函数时,究竟调用哪一份实现代码,取决于发出调用的那个对象的动态类型。

Virtual函数是动态绑定,而缺省参数值却是静态绑定。意思是你肯呢过会在“调用一个定义于derived class内的virtual函数”的同时,却使用base class为它所指定的缺省参数值。什么是动态类型什么是静态类型呢?动态类型是这个指针指向的对象时什么类型,静态类型是这个指针的声明类型是什么?

绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数是动态绑定。

时间: 2024-10-07 17:17:21

Effective C++ --经验条款的相关文章

《Effective C++》条款20宁以pass-by-reference-to-const替换pass-by-value

<Effective C++> 条款20:宁以pass-by-reference-to-const替换pass-by-value 缺省情况下C++以by value方式传递对象至函数.除非你另外知道,否则函数参数都是以实际参数的副本为初值,而调用端所获得的亦是函数返回值的一个复件.这些复件系由copy构造函数产出,这可能使得pass-by-value成为昂贵的费时的操作. 通过pass-by-reference-to-const的传递方式效率高的多:原因是没有任何构造函数或析构函数被调用,因为

高效C++ --经验条款(三)

高效C++ --经验条款(三) 给多态基类声明virtual析构函数: "给base classes一个virtual析构函数",这个规则只适用于带有多态性质的base classes身上.这种base classes的设计目的是为了用来"通过base class接口处理derived class对象". 并非所有base classes的设计目的都是为了多态用途.例如标准stirng和STL容器都不被设计作为base classes使用,更别提多态了.某些clas

Effective C++:条款36:绝不重新定义继承而来的non-virtual函数

(一)首先有下面的继承体系: class B { public: void mf(); ... }; class D : public B {...}; D x; 以下行为: B* pB = &x; pB->mf(); 异于以下行为: D* pD = &x; pD->mf(); 上面两种行为产生的结果不一定相同.看下面这种情况: mf是个non-virtual函数而D定义有自己的mf版本: class D : public B { public: void mf(); ...

Effective C++:条款37:绝不重新定义继承而来的缺省参数值

由于重新定义继承而来的non-virtual函数是不正确的(见上一个条款),所以这个条款就将问题局限于:绝不重新定义继承一个带有缺省参数值的virtual函数. (一) virtual函数是动态绑定的,而缺省参数却是静态绑定. 对象的所谓静态类型,是它在程序中被声明时所采用的类型. 你可能会在"调用一个定义于derived class 内的virtual函数"的同时,却使用了base class为它所指定的缺省参数值. (二) 为什么继承而来的virtual函数的缺省参数值不能被重新定

Effective C++:条款35:考虑virtual函数以外的其他选择

游戏中的人物伤害值计算问题. (一)方法(1):一般来讲可以使用虚函数的方法: class GameCharacter { public: virtual int healthValue() const; //返回人物的体力值,派生类可以做出修改 ... }; 这确实是一个显而易见的设计选择.但因为这样的设计过于显而易见,可能不会对其它可选方法给予足够的关注.我们来考虑一些处理这个问题的其它方法. (二)方法(2):使用NVI方法,在基类中使用一个公有的普通函数调用私有的虚函数. class G

Effective C++:条款22:将成员变量声明为private

(一)为什么不采用public成员变量 (1)首先,从语法一致性考虑,客户唯一能访问对象的方法就是通过成员函数,客户不必考虑是否该记住使用小括号(). (2)其次,使用函数可以让我们对成员变量的处理有更精确的控制.如果我们令成员变量为public,那么每个人都可以读写它! 但如果我们以函数取得或设定其值,我们就可以实现出"不准访问"."只读访问"以及"读写访问",我们甚至可以实现"惟写访问". class AccessLeve

Effective C++:条款18:让接口容易被正确使用,不易被误用

(一) 看下面这个例子: class Date { public: Date(int month, int day, int year); }; 很有可能引起下面这两个错误: (1)他们也许会以错误的次序传递参数,如:Date d(30, 3, 1995); (2)他们可能传递一个无效的月份或天数,如:Date d(2, 30, 1995); 许多像这类客户端错误. 解决方法:简单的外覆(wrapper types)类型来区别天数.月份.和年份,然后于Date构造函数中使用这些类型: struc

Effective C++:条款38:通过复合塑模出has-a或“根据某物实现出”

(一) public继承是"is-a"的关系,而复合有"has-a"或"根据某物实现出(is-implemented-in-terms-of)"的意思--当复合发生在应用域内的对象之间,表现出has-a关系:当它发生于实现域内则是表示"根据某物实现出"的关系. 应用域部分,相当于你塑造的世界中的某些事物,例如人,汽车等. 后者的对象则是实现细节人工产品(这产品现实世界中是没有的),像什么mutex,list,container

Effective C++:条款33:避免遮掩继承而来的名称

(一) 下面这段代码: int x; void someFunc() { double x; //local variable std::cin>>x; //read a new value to local x } 这个指涉的是local变量x,而不是global变量x,因为内存作用域会的名称遮掩外围作用域的名称.当编译器处于someFunc的作用域内并遭遇名称x时,他在local作用域内查找是否有什么东西带着这个名称.如果找到就不再找其他作用域.someFunc的x是double类型而gl