C++ primer 继承与动态绑定

数据抽象(data abstraction),继承(inheritance)与动态绑定(dynamic binding)是面向对象编程(object-oriented programming)的三大核心思想(key ideas)。

数据抽象好理解,就是使得我们将类的接口与实现分离

继承与动态绑定在使用上是相关的


这里我们注意几点:

1.继承类(derived class)需要在自己内部(就是class{...}内部)有它打算自己实现的(defile it self)虚函数(virtual function) 的声明(declaration).这句话听起来好像是废话,我当然要声明了 ,但我感觉想表达的重点是这样的:你需要自己内部(own class body)声明,你想修改的基类function,当然基类中你想要修改的function 都是virtual function ,如果没有内部声明基类中的部分virtual function ,那么对于继承类来讲就相当于无修改直接继承这个函数(inherit without change)


2.动态绑定dynamic binding  or  run-time binding

C++ primer原文是这样说的:

In C++ ,dynamic binding happens when a virtual funtion is called through a reference(or a pointer)to a base class

.在C++中,动态绑定发生的场景的两个条件: virtual funtion    和 a reference(or a pointer)to a base class 。

首先你调用的要是一个虚函数,其次是引用或者指针调用的。

所以在实际工程中,要实现动态绑定,我们传的参数都是用引用或者指针。


3.作为基类,它的function ,需要区分为期望继承类override的(即继承类自己define it self的)和期望继承类能够 无修改直接继承的(inherit without change)。

对于期望继承类override的function,我们要在基类中,将这项function 定义为virtual ,具体操作就是在声明前加上关键字virtual , 也就是所谓的将这个function定义为了虚函数。就像2中说讲的,我们使用引用或者指针call 虚函数,实现动态绑定


A function this is declared as virtual in the base class is implictly virtual in derived class as well.

4.一个在基类中声明的虚函数,在继承类中会隐式地(implicitly)为virtual

下面我们举几个例子说明,并观察结果

例1:

class A{
public :
	void Print()
	{
		printf("A\n");
	}
};


class B :public A{
public:
	void Print()
	{
		printf("B\n");
	}
};


void Show(A &a)
{
	a.Print();
}
int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B b;
	Show(a);
	Show(b);
	return 0;
}
运行的结果为:

A

A

因为基类A 中的Print函数并没有声明为virtual ,所以无法实现动态绑定,所以a.Print都是调用A的function 。

例2:

不同于例1的地方就是在A 的Print 函数前加上virtual keyword

class A{
public :
	virtual void Print()
	{
		printf("A\n");
	}
};

class B :public A{
public:
	void Print()
	{
		printf("B\n");
	}
};

void Show(A &a)
{
	a.Print();
}
int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B b;
	Show(a);
	Show(b);
	return 0;
}

运行的结果为:

A

B

base class A函数Print 已经被声明为virtual ,可以进行动态绑定,且Show中的传入参数a为引用。在调用Show(b)时,这时候Show里面的a.Print,调用的其实是class B中的Print

例3:

不同于例2的地方是show函数的传入参数不用引用 而是普通形参

class A{
public :
	virtual void Print()
	{
		printf("A\n");
	}
};

class B :public A{
public:
	void Print()
	{
		printf("B\n");
	}
};

void Show(A a)
{
	a.Print();
}
int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B b;
	Show(a);
	Show(b);
	return 0;
}

运行的结果为:

A

A

结果与例2不同,这是因为Show的传入参数不是引用或者指针,这样,show中的a,一定是A类型 ,无法改变,脱离的动态二字。

具体原因就是传参类型不同,这里需要理解传参的机制是如何的,其实引用是变相的传递指针,只是比指针更加安全,不容易引起崩溃问题,具体原因请看引用的原理。


动态绑定时,调用时的类都是较底层类型,就是在这个继承层次(hierarchy)中,都是 较底层类型(基类) 动态调用 较高层类型(继承类)


今天写到这里,后面继续补充...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值