Visual c++ 是否从基类内调用派生类方法?

Visual c++ 是否从基类内调用派生类方法?,visual-c++,inheritance,c++-cli,polymorphism,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 OverridenMeth

我试图让一个非虚拟基类方法调用一个派生方法,该方法重写基类的一个虚拟方法。就我个人而言,我无法让它工作。请参阅下面的代码:

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();
}
使用上面的代码,将调用基类的OverridedMethod()而不是派生类的OverridedMethod(),这不是我想要的。我的印象是,在使用多态性时,对被重写的基类方法的调用应该调用派生类的重写方法

我也尝试过使用摘要:

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()定义内调用OverridedMethod时,这会导致C3278编译器错误(直接调用接口方法“interface method”将在运行时失败)。

首先,至少不应编译第一个代码示例,因为方法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;
}
或者类可以定义为

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()" ); }
};
结果与调用派生类的虚函数相同。

解决方案由OP提供

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


这就是为什么在使用abstract关键字时,在基类的Run()定义内调用OverridedMethod()时出现C3278错误的原因。这是因为我调用的是BaseClass::OverridedMethod(),它只指向一个抽象定义。

Mgetz:谢谢你给我指出这篇文章。但是,它只讨论使用基类和派生类的引用在外部调用重写的方法。我的问题是从基类中调用重写的方法。另外,我在上面的示例中使用了override,在第二个示例中没有使用,因为它使用的是abstract。@pcdangio您需要使用
override
,无论在这种特殊情况下如何。还要注意,您需要设置访问修饰符,以便dirived类可以重写基类class@Mgetz你错了。至少MS VC++2010编译器要求必须指定虚拟,即使存在重写。有趣的。。。VS2013不。。。正如我的答案在/clr pure中编译和运行一样fine@Mgetz可能是因为关键词抽象。据我所知,如果一个函数是抽象的,那么它就是虚拟的。@VladFrommosco:谢谢你发布你的代码。。。通过它,我发现了我的错误。我的代码与您的代码一样,但是它仍然在控制台上打印“A::g()。这是因为我调用了A::g(),而不是A::f()方法定义中的g()。发生这种情况是因为我使用headers/cpp来定义我的类,在我的cpp中,每当我以任何方式引用该方法时,我通常使用ClassName::MethodName()。另外,很抱歉没有输入private/protected指示符,我刚刚输入了一个代码的快速表示,但忘记了hah@pcdangio看来我的程序示例帮助您找到了错误祝您好运!
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()" ); }
};
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!!!!!
    }
};