虚继承、虚函数

1. 虚继承简单的说就是如果有两个类都继承了同一个基类(A),那么,如果有第三个类又继承了这两个类,第三个类就会出现有      两个基类(A)的情况,虚继承就能避免这种情况。

    从实现代码来看:

    普通继承:

/**
	普通继承(没有使用虚基类)
*/
 
// 基类A
class A
{
public:
	int dataA;
};
 
class B : public A
{
public:
	int dataB;
};
 
class C : public A
{
public:
	int dataC;
};
 
class D : public B, public C
{
public:
	int dataD;
};

  虚继承:

/**
	虚继承(虚基类)
*/
 
#include <iostream>
 
// 基类A
class A
{
public:
	int dataA;
};
 
class B : virtual public A
{
public:
	int dataB;
};
 
class C : virtual public A
{
public:
	int dataC;
};
 
class D : public B, public C
{
public:
	int dataD;
};

  从实现原理来说,就是虚继承的话 派生类对象 会产生一个 虚表指针(就是一个指针),指向一个虚表 ,对象D 继承了B、C

  也会同时继承两个虚表指针,两个虚表指针指向的虚表上有记录 B、C 都有的基类在对象D ,内存中的一个偏移距离,从而

   实现了D中指挥有一个A 。

   建议大家还可以去看看这个大神的博客   http://blog.csdn.net/xiejingfa/article/details/48028491 

2.  虚函数 

     先说一下C++ 有动态绑定和静态绑定的区别。 静态绑定是指编译器在编译的时候就完成了绑定,比如函数重载,编译器会根据传递给函数的参数就可以判定使用哪一个重载函数。

     而动态绑定,就是靠虚函数的机制来实现的,并实现了多态机制,多态是面向对象程序设计语言的基本特征之一。在C++中,多态就是利用基类指针指向子类(注意:只能子类转换成基类)实例,然后通过基类指针调用子类(虚)函数,从而实现一个接口,多种形态的效果。(可能有点绕,多读几遍就好了)

  或者使用基类的引用来调用虚函数也可实现

下面 用一个简单的例子看看效果啦:

class Base1 
{
public:
    virtual void func1() { cout << "Base1::func1()" << endl; }
    void func2() { cout << "Base1::func2()" << endl; }
};

class Base2 : public Base1
{
    void func1() { cout << "Base2::func1()" << endl; }
};

int main()
{
    cout << "virtual function testing:" << endl;
    Base2 b;
    Base1 *ptr = &b;
    ptr->func1();
    ptr->func2();
}

输出结果: 自己理解理解,注意我上面讲的动态绑定。

下面讲一下具体实现原理:

 每一个带虚函数的类对象在内存地址的开头都会有一个虚表指针 指向了一个虚表,表上记录了对象内 虚函数 的地址。

 每一个继承了 这个带虚函数 的类 实例化的对象(并且重写了,基类中的虚函数),也会有一个虚表指针,并且这虚表指针之指向的虚表上记录的是 是当前类内的 (已经重写的)那个函数的地址。

 这样的话,当用基类指针指向子类实例时就会用虚表上记录的函数来调用了,也就是会调用基类重写后的。

猜你喜欢

转载自blog.csdn.net/qq_35712835/article/details/82900951