从基类中调用派生类方法?

时间:2014-02-17 22:31:19

标签: visual-c++ inheritance c++-cli polymorphism

我试图让一个非虚基类方法调用一个派生方法来覆盖其中一个基类的虚方法。对于我的生活,我无法让它发挥作用。请参阅以下代码:

public ref class BaseClass
{
    virtual void OverriddenMethod(){}

    void Run()
    {
        // Do some initial work here.

        // Call the derived class's version of OverridenMethod to do final work:
        OverriddenMethod();
    }
};

public ref class DerivedClass : public BaseClass
{
    virtual void OverriddenMethod() override
    {
        // Do some final work here.
    }
};

int main()
{
    DerivedClass^ DC = gcnew DerivedClass();
    DC->Run();
}

使用上面的代码,调用基类的OverriddenMethod()而不是派生类的OverriddenMethod(),这不是我想要的。我的印象是,在使用多态时,对被重写的基类方法的调用应该调用派生类的重写方法。

我也尝试过使用抽象:

public ref class BaseClass abstract
{
    virtual void OverriddenMethod() abstract;

    void Run()
    {
        // Do some initial work here.

        // Call the derived class's version of OverridenMethod to do final work:
        OverriddenMethod();
    }
};

public ref class DerivedClass : public BaseClass
{
    void OverriddenMethod()
    {
        // Do some final work here.
    }
};

int main()
{
    DerivedClass^ DC = gcnew DerivedClass();
    DC->Run();
}

但是当在BaseClass :: Run()定义中调用OverriddenMethod时,这会产生C3278编译器错误(接口方法'接口方法'的直接调用将在运行时失败)。

2 个答案:

答案 0 :(得分:1)

首先,至少你的第一个代码示例不能编译,因为方法Run有私有访问控制。

为了简单起见,我尝试了对代码进行一些修改的代码,并得到了所需的结果

#include "stdafx.h"

using namespace System;

public ref class A
{
public:
    void f() { g(); }
    virtual void g() { Console::WriteLine( "A::g()" ); }
};

public ref class B : public A
{
public:
    virtual void g() override { Console::WriteLine( "B::g()" ); }
};


int main(array<System::String ^> ^args)
{
    A ^pa = gcnew B();
    pa->f();
    return 0;
}

输出

B::g()

或者类可以定义为

public ref class A
{
public:
    void f() { g(); }
protected:
    virtual void g() { Console::WriteLine( "A::g()" ); }
};

public ref class B : public A
{
protected:
    virtual void g() override { Console::WriteLine( "B::g()" ); }
};

结果与调用派生类的虚函数相同。

答案 1 :(得分:0)

OP解决方案。

public ref class BaseClass abstract
{
    virtual void BaseClass::OverriddenMethod() abstract;

    void BaseClass::Run()
    {
        // Do some initial work here.

        // Call the derived class's version of OverridenMethod to do final work:
        BaseClass::OverriddenMethod();  // DONT DO THIS!!!!!!!!
        OverriddenMethod(); // DO THIS INSTEAD!!!!!
    }
};

这里的问题是因为我使用标题定义和cpp文件来实现我的基类。在cpp文件中,我通常使用ClassName :: MemberName表示法来引用任何ClassName的成员。但是,在这种情况下这样做会强制调用基类的虚方法而不是派生类中的重写方法。

这就是为什么在使用abstract关键字时,我在基类的Run()定义中调用OverriddenMethod()时遇到了C3278错误。因为我正在调用BaseClass :: OverriddenMethod(),它只指向抽象定义。