effective C++ 读书笔记 条款36-37

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

重要点:non-virtual函数都是静态绑定

// 1241.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

class Base
{
public:
	void func()
	{
		cout<<"Base::func()"<<endl;
	}
};

class Derived : public Base
{
public:
	void func()
	{
		cout<<"Derived::func()"<<endl;
	}
};
int _tmain(int argc, _TCHAR* argv[])
{

	Derived test;
	Base* pB = &test;

	Derived* pD = &test;

	pB->func();//调用Base::func()
	pD->func();//调用Derived::func()
	/*
	这里我们讨论的不是关于隐藏的问题;上面pB指向一个子类,但是调用的是父类的func()函数,至于为什么,因为不是虚函数,没有virtual;
	要明白一点:non-virtual函数 Base::func and Derived::func都是静态绑定的,pB被声明为一个人 pointer-to-Base,通过pB调用的non-virtual
	函数永远是Base所定义的版本,即使pB指向一个类型为它的派生类的对象。
	pD 调用的是Derived的函数版本,这里也可以说成是隐藏,但是最终原因是因为 静态绑定。
	一般  Derived dTest,dTest.func()这样调用我们一般说是因为隐藏。对于对象,而我们本例子当中对应的是指针或者引用,是因为静态绑定!

	*/

	getchar();
	return 0;
}

总上:任何情况下都不应该重新定义一个继承而来的non-virtual函数;

对于一个基类来说,如果一个函数定义为非虚函数,那么意味着这个函数并不想改变,所以子类不应该继承它,一个类当中的非虚函数,不变性凌驾于其特异性上。

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

virtual函数是动态绑定,缺省参数值是静态绑定;

// 1240.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

class  Shape
{
public:
	enum ShapeColor{Red,Green,Blue};
	virtual void draw(ShapeColor color = Red) const = 0;

};

class Rectangle:public Shape
{
public:
	virtual void draw(ShapeColor color = Green) const
	{
		cout<<"Rectangle"<<endl;
	}
};

class Circle : public Shape
{
public:
	virtual void draw(ShapeColor color) const
	{
		cout<<"Circle"<<endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{

	Shape* ps;
	Shape* pc = new Circle;
	Shape* pr = new Rectangle;

	pr->draw();//这里调用的是Rectangle的draw函数,但是函数参数color却是Shape父类里面的参数
	/*
	virtual函数是动态绑定,而缺省参数值却是静态绑定。
	这就出现了上面的 调用一个定义于子类的virtual函数,同时却使用base class为它所指定的缺省参数值。
	pr的动态类型是Rectangle*,所以调用的是Ractangle的virtual函数,但是由于pr的静态类型是Shape*,所以此
	函数调用的缺省参数值却是来自鱼Shape Class.
	*/
	getchar();
	return 0;
}

总结:不要重新定义一个继承而来的缺省参数值,因为缺省参数值是静态绑定的,而virtual函数--你唯一应该覆写的东西--却是动态绑定!!

时间: 2024-10-30 01:07:14

effective C++ 读书笔记 条款36-37的相关文章

effective C++ 读书笔记 条款06

条款06:若不想使用编译器自动生成的函数,就该明确拒绝: 直接看代码与注释: #include <iostream> using namespace std; class Test { public: Test() { } ~Test() { } /* void TT() { Test t1; Test t2(t1); } */ private: Test(const Test& test); Test& operator = (const Test& test); }

Effective C++读书笔记(条款35-40)

(六).继承与面向对象设计 ____________________________________________________________________________________________________________________________________ 条款35:考虑virtual函数以外的其他选择 #1.virual函数的四个替代方案: (1).使用non-virtual interface(NVI)手法,那是 Template Method 设计模式

Effective C++读书笔记(条款24-29)

Effective C++第四篇,扩展的有点多... (四).设计与声明 ____________________________________________________________________________________________________________________________________ 条款24:若所有参数皆需类型转换,请为此采用non-member函数 #1.如果你需要为某个函数的所有参数(包括被 this指针所指的那个隐喻参数)进行 类型转

Effective C++读书笔记(条款1-10)

不得不说,Effective C++确实是一本C++进阶的好书,刚浏览完第二遍, 现对其做一个大体性的总结 ,并进行适当的展开,作为以后C++参考复习之用. (一).让自己习惯C++ ____________________________________________________________________________________________________________________________________ 条款1:视C++为一个语言联邦 #1.将C++ 分

effective C++ 读书笔记 条款20

条款20:宁以 pass-by-reference-to-const 替换 pass -by -value 1:采用后者效率高:看代码: #include <iostream> using namespace std; class Person { public: Person() { cout<<"Person()"<<endl; } Person(const Person& p) { cout<<"Person(co

effective C++ 读书笔记 条款11

条款11: 在operator= 中处理"自我赋值" 在实现operator=时考虑自我赋值是必要的就像 x=y .我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指针更恰当一点). 例如以下 第一版: #include <iostream> using namespace std; class bitmap { public: bitmap() { cout<<"调用bitmap()无參构造函数"<<endl; }

effective C++ 读书笔记 条款08

条款08  别让异常逃离析构函数: 假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去) 看代码: #include <iostream> using namespace std; class DBConnection { public: void close() { int i = 3; int j = 0; int k = i/j; printf("%d\n",k); } }; class DBConn { public: DBC

Effective C++读书笔记(条款18-23)

(四).设计与声明 ____________________________________________________________________________________________________________________________________ 条款18:让接口容易被使用,而不容易被误用 #1.导入新类型可以让接口不易被误用,以函数替换对象则可以保证类型安全性. 例如: class Date{ public: Date(int month, int day

effective C++ 读书笔记 条款12与条款13

条款12:确定你的public继承塑膜出is-a关系: 这个条款主要将了一些特殊情况:比如企鹅是鸟,企鹅可以继承于鸟,但是鸟会飞,企鹅却不能飞:还有让正方形继承矩形可能也会造成这种尴尬! 这个问题以前想过,但是不知道怎么解决,如果现实生活当中确实要这么使用:比如 猫 狗 鱼  猪等等许多动物继承Animal类,但是猫狗等不会游泳, 假如这里是有很多动物,不能采用鱼里面专门加一个方法!  这个现在还没想出来,条款12也没有讲如果要这么用该怎么处理就是将要避免这样. is - a; 在面向对象程序设