wenmingxing 发表于 2016-8-18 17:40:21

C++类中只有通过指针调用函数的时候才能形成覆盖的效果吗

本帖最后由 wenmingxing 于 2016-8-18 17:42 编辑

C++ 类中只有通过指针调用函数才能形成   覆盖   吗

浅云纸月 发表于 2016-8-18 18:42:28

不大明白你的意思, 可以说清楚些吗

wenmingxing 发表于 2016-8-18 19:31:23

浅云纸月 发表于 2016-8-18 18:42
不大明白你的意思, 可以说清楚些吗

就是只有通过指针的形式调用函数才能形成覆盖基类函数的效果吗,如果不通过指针调用那直接通过a.fun这种形式不就相当于基类函数没有被覆盖吗
#include<iostream>

using namespace std;

class A
{
public :
    virtual void play();
};

class B : public A
{
public :
    void play();
};

void A :: play()
{
    cout << "AAA" << endl;
}

void B :: play()
{
    cout << "BBB" << endl;
}

main()
{
    A a;
    B b;

    a.play();         //不覆盖

    A *aa;
    aa=&b;

    aa -> play();             //覆盖
}


上面例子main中的a.play就是没有覆盖效果输出AAA,a->play覆盖输出BBB

浅云纸月 发表于 2016-8-18 20:59:24

本帖最后由 浅云纸月 于 2016-8-19 22:46 编辑

直接在外部调用基类A的函数也可以实现 ...不过确实可以实现, 会麻烦一点.我写了下代码, 你看一下, 不懂的尽管问


#include "stdafx.h"
#include <iostream>

#include <windows.h>


using namespace std;

class A
{
public:
        virtual void play();
};

class B : public A
{
public:
        void play();
};

void A::play()
{
       
        cout << "AAA" << endl;
}

void B::play()
{
        cout << "BBB" << endl;
}

int main()
{
        // 获取类 A 的 vftable
        struct tagCLASS
        {
                DWORD *pVMT;
        };
        A a;
        DWORD *pVMT = ((tagCLASS *)(&a))->pVMT;

        // 获取 vftable 中的 play() 函数的内存地址
        static void(__fastcall *pfnA_Play)(void *pthis) = NULL;
        pfnA_Play = (void(__fastcall *)(void *pthis))pVMT;

        B b;
        A* aa = &b;

        // 调用 类A 的play()函数
        pfnA_Play(aa);

    return 0;
}

Krant5 发表于 2016-8-19 22:26:34

其实应该是指针和引用都可以的,在使用虚函数的前提下可以实现动态编联,能够正确的调用对象的函数

vcvycy 发表于 2016-8-19 23:10:51

这就要从汇编层面上看了:每一个对象头部4Bytes指向虚函数表,对象A和对象B都有一个虚函数表,如果用指针P的话,P指向A就用A的虚函数表,P指向B就用B的虚函数表,这么简单的一个东西就实现了所谓多态性。不用指针的话,用的虚函数表都是不变的,所以每一个对象用到的函数都不会变。

iszhuangsha 发表于 2016-8-21 23:20:10

基函数中函数声明为虚函数,在用指针调用的过程中实现动态绑定。这是面向对象语言的多态性。另外,你的代码有问题。
#include<iostream>

using namespace std;

class A
{
public :
    virtual void play();
};

class B : public A
{
public :
    void play();
};

voidA :: play()
{
    cout << "AAA" << endl;
}

void B :: play()
{
    cout << "BBB" << endl;
}

int main()
{
    A a;
    B b;

    a.play();         //调用基类的函数,输出AAA
        b.play();                        //调用继承类的函数,输出BBB
    A *aa;
    aa=&b;                                       

    aa -> play();      //实现类的动态绑定,输出BBB
       
}
页: [1]
查看完整版本: C++类中只有通过指针调用函数的时候才能形成覆盖的效果吗