C++ dynamic binding

#include<iostream>
#include <string>

class Base {
public:
	virtual void sayHello() { std::cout << "Hello from base" << std::endl; }
	virtual void sayHi() { std::cout << "Hi from base" << std::endl; }
	virtual void sayHappy() { std::cout << "Happy from base" << std::endl; }
	std::string isbn() const;
	//virtual double net_price(std::size_t n) const;
};
class Derived : public Base {
public:
	//implictly overide corresponding virtual functions of base class, though not explicitly them as virtual functions
	void sayHappy() { std::cout << "Happy from derived class" << std::endl; } 
	void sayHello() { std::cout << "Hello from derived class" << std::endl; }
	void sayHi() { std::cout << "Hi from derived class" << std::endl; }
	
};


int main() {
	typedef void (**ppf)(void);
	typedef void(*pf)(void);

	Base *qt, aa;

	Derived dd;
	dd.sayHello();
	qt = &dd;
	qt->sayHello();
//get address of the vftable
	int *vTableAddress = (int*)(&dd);
	
//vTable is the pointer to the first element of the vftable
	ppf vTable = ((ppf)(*vTableAddress));
//thses are pointers in the vftable
	pf say_hello = *vTable;
	pf say_hi = *(vTable + 1);
	pf say_happy = *(vTable + 2);
	for (int i = 0; i < 10; i++) {
		std::cout << *(vTable + i) << std::endl;
	}
	

	//依次调用 sayHello(), sayHi(), sayHappy()
	say_hello();
	say_hi();
	say_happy();

	return 0;
}

通过以上代码实验得到的结论是:

Base *p;

Derived d;

p = &d;

p.vfunc();

通过指向基类的指针来调用虚函数时的顺序是,

在编译期间“:

在基类非虚函数中找要调用的函数,如果找到的话,则调用的就是该方法,不再继续找了;

如果在非虚函数中没有找到的话,则在基类的虚函数表找,如果找到的话,记录该函数在虚函数表中的偏移量,则运行时实际调用的就是刚才找到的那个虚函数对应于指针p指向的那个对象的虚函数,即,只有等到runtime时才能知道调用的是那个虚函数;

如果都没找的话,就在编译时出错。

在新标准下,子类函数中函数名和基类虚函数同名的函数如果不声明virtual,编译器默认把他们当作虚函数对待,同时子类虚函数在虚函数表中的顺序与基类中虚函数表中的相应虚函数的顺序一致。这是因为直接用在编译期间找到那个偏移量加上运行时实际调用那个虚函数表的地址,得到的结果就是指向实际要调用的那个虚函数的指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值