覆盖具有相同名称的C ++虚函数,但保留对象二进制可分隔

时间:2017-04-19 14:58:28

标签: c++ polymorphism

我有基类和虚方法fun。我需要重新定义派生类中的所有fun方法。我知道SO: C++ virtual override functions with same name,但它对我不起作用。

功能processDerived接受v1::Derived *。如果我通过v2::Derived *,它就无法正常工作。

class Base1 {
public:
    virtual ~Base1() {}
    virtual void funB1_1() {}
    virtual void funB1_2() {}
    virtual void fun() { std::cout << "Base1::fun()" << std::endl; }
};

class Base2 {
public:
    virtual ~Base2() {}
    virtual void fun() { std::cout << "Base2::fun()" << std::endl; }
    virtual void funB2() {}
};

namespace v1 {

    class Derived : public Base1, public Base2 {
        int x_;
    public:
        Derived() : x_(10) {}
        virtual ~Derived() {}
        virtual void funD1(int i) { std::cout << "Derived::funD1(" << i << ")" << std::endl; }
    };

}

namespace v2 {

    class Base1Proxy : public Base1 {
    public:
        virtual ~Base1Proxy() {}
        virtual void fun() override { fun_Base1(); }
    protected:
        virtual void fun_Base1() = 0;
    };

    class Base2Proxy : public Base2 {
    public:
        virtual ~Base2Proxy() {}
        virtual void fun() override { fun_Base2(); }
    protected:
        virtual void fun_Base2() = 0;
    };

    class Derived : public Base1Proxy, public Base2Proxy {
        int x_;
    public:
        Derived() : x_(10) {}
        virtual ~Derived() {}
        virtual void funD1(int i) { std::cout << "Derived::funD1(" << i << ")" << std::endl; }
    protected:
        virtual void fun_Base1() override { std::cout << "Derived::Base1::fun(), x = " << x_ << std::endl; }
        virtual void fun_Base2() override { std::cout << "Derived::Base2::fun(), x = " << x_ << std::endl; }
    };

}

void processDerived(v1::Derived * d, int i) {
    d->funD1(i);
}

int main() {
    v1::Derived d;
    Base1 * b1 = &d;
    Base2 * b2 = &d;
    b1->fun();
    b2->fun();
    processDerived(&d, 100);

    v2::Derived d2;
    b1 = &d2;
    b2 = &d2;
    b1->fun();
    b2->fun();
    processDerived(reinterpret_cast<v1::Derived *>(&d2), 200);
}

输出:

Base1::fun()
Base2::fun()
Derived::funD1(100)
Derived::Base1::fun(), x = 10
Derived::Base2::fun(), x = 10
Derived::Base1::fun(), x = 10  // expected Derived::funD1(200)

VTABLES(由MSVC生成):

;   COMDAT ??_7Derived@v2@@6BBase2Proxy@1@@
CONST   SEGMENT
??_7Derived@v2@@6BBase2Proxy@1@@ DQ FLAT:??_R4Derived@v2@@6BBase2Proxy@1@@ ; v2::Derived::`vftable'
    DQ  FLAT:??_EDerived@v2@@W7EAAPEAXI@Z
    DQ  FLAT:?fun@Base2Proxy@v2@@UEAAXXZ
    DQ  FLAT:?funB2@Base2@@UEAAXXZ
    DQ  FLAT:?fun_Base2@Derived@v2@@MEAAXXZ
CONST   ENDS
;   COMDAT ??_7Derived@v2@@6BBase1Proxy@1@@
CONST   SEGMENT
??_7Derived@v2@@6BBase1Proxy@1@@ DQ FLAT:??_R4Derived@v2@@6BBase1Proxy@1@@ ; v2::Derived::`vftable'
    DQ  FLAT:??_EDerived@v2@@UEAAPEAXI@Z
    DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
    DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
    DQ  FLAT:?fun@Base1Proxy@v2@@UEAAXXZ
    DQ  FLAT:?fun_Base1@Derived@v2@@MEAAXXZ
    DQ  FLAT:?funD1@Derived@v2@@UEAAXH@Z
CONST   ENDS

;   COMDAT ??_7Base2Proxy@v2@@6B@
CONST   SEGMENT
??_7Base2Proxy@v2@@6B@ DQ FLAT:??_R4Base2Proxy@v2@@6B@  ; v2::Base2Proxy::`vftable'
    DQ  FLAT:??_EBase2Proxy@v2@@UEAAPEAXI@Z
    DQ  FLAT:?fun@Base2Proxy@v2@@UEAAXXZ
    DQ  FLAT:?funB2@Base2@@UEAAXXZ
    DQ  FLAT:_purecall
CONST   ENDS

;   COMDAT ??_7Base1Proxy@v2@@6B@
CONST   SEGMENT
??_7Base1Proxy@v2@@6B@ DQ FLAT:??_R4Base1Proxy@v2@@6B@  ; v2::Base1Proxy::`vftable'
    DQ  FLAT:??_EBase1Proxy@v2@@UEAAPEAXI@Z
    DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
    DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
    DQ  FLAT:?fun@Base1Proxy@v2@@UEAAXXZ
    DQ  FLAT:_purecall
CONST   ENDS

;   COMDAT ??_7Derived@v1@@6BBase2@@@
CONST   SEGMENT
??_7Derived@v1@@6BBase2@@@ DQ FLAT:??_R4Derived@v1@@6BBase2@@@ ; v1::Derived::`vftable'
    DQ  FLAT:??_EDerived@v1@@W7EAAPEAXI@Z
    DQ  FLAT:?fun@Base2@@UEAAXXZ
    DQ  FLAT:?funB2@Base2@@UEAAXXZ
CONST   ENDS
;   COMDAT ??_7Derived@v1@@6BBase1@@@
CONST   SEGMENT
??_7Derived@v1@@6BBase1@@@ DQ FLAT:??_R4Derived@v1@@6BBase1@@@ ; v1::Derived::`vftable'
    DQ  FLAT:??_EDerived@v1@@UEAAPEAXI@Z
    DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
    DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
    DQ  FLAT:?fun@Base1@@UEAAXXZ
    DQ  FLAT:?funD1@Derived@v1@@UEAAXH@Z
CONST   ENDS

;   COMDAT ??_7Base2@@6B@
CONST   SEGMENT
??_7Base2@@6B@ DQ FLAT:??_R4Base2@@6B@          ; Base2::`vftable'
    DQ  FLAT:??_EBase2@@UEAAPEAXI@Z
    DQ  FLAT:?fun@Base2@@UEAAXXZ
    DQ  FLAT:?funB2@Base2@@UEAAXXZ
CONST   ENDS

;   COMDAT ??_7Base1@@6B@
CONST   SEGMENT
??_7Base1@@6B@ DQ FLAT:??_R4Base1@@6B@          ; Base1::`vftable'
    DQ  FLAT:??_EBase1@@UEAAPEAXI@Z
    DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
    DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
    DQ  FLAT:?fun@Base1@@UEAAXXZ
CONST   ENDS

如您所见,方法(1)被调用而不是(2)

; old Derived::`vftable'
DQ  FLAT:??_EDerived@v1@@UEAAPEAXI@Z
DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
DQ  FLAT:?fun@Base1@@UEAAXXZ
DQ  FLAT:?funD1@Derived@v1@@UEAAXH@Z

; new Derived::`vftable'
DQ  FLAT:??_EDerived@v2@@UEAAPEAXI@Z
DQ  FLAT:?funB1_1@Base1@@UEAAXXZ
DQ  FLAT:?funB1_2@Base1@@UEAAXXZ
DQ  FLAT:?fun@Base1Proxy@v2@@UEAAXXZ
DQ  FLAT:?fun_Base1@Derived@v2@@MEAAXXZ   ; <== (1)
DQ  FLAT:?funD1@Derived@v2@@UEAAXH@Z      ; <== (2)

我的案子有解决方案吗?

P.S。 我知道MSVC特定的解决方案,但我需要它为GCC,Clang,Apple-Clang工作。

0 个答案:

没有答案