虚拟方法的委托,它指向哪个(基础/派生)?

时间:2012-12-13 09:05:15

标签: delegates c++-cli virtual-inheritance

我最近开始使用C ++ / Cli进行包装。 现在我正处于一个我需要了解更多关于内部结构的地方。

请考虑以下代码:

Header file (ignoring .NET namespaces for this example):

public ref class BaseyClass
{
    protected:
        delegate void TestMethodDelegate(); // TestMethod delegate
        BaseyClass();                       // constructor            
        virtual void TestMethod();          // member: method
        GCHandle _testMethodHandle;         // member: method handle
};


CPP file (ignoring .NET namespaces for this example):

BaseyClass::BaseyClass()
{
    _testMethodHandle
          = GCHandle::Alloc(
                       gcnew TestMethodDelegate(this, &BaseyClass::TestMethod));
}

void TestMethod()
{
}

最终这个类将在以后用作基类(对于DerivedClass),并且方法“TestMethod()”将被覆盖并通过委托指针从非托管代码调用。

现在的问题是:委托将引用哪种方法?

BaseyClass :: TestMethod的();

DerivedClass :: TestMethod的();

我个人认为委托会引用“BaseyClass :: TestMethod()”,因为即使重写它,委托也指向BaseyClass的(base-)地址。因此,DerivedClass不能覆盖“TestMethod”并使用BaseyClass中的委托。

我只是想确定一下。感谢您的评论和启发。

1 个答案:

答案 0 :(得分:1)

委托将是派生类的TestMethod的引用。即使您传递&BaseyClass::TestMethod,这是一个虚方法,您也传递this,这是派生类型,并且在创建委托时会考虑这两者。

其他说明:

  • TestMethodDelegate不需要在类定义中。更标准的方法是将委托放在类之外,只在命名空间中。 (或使用现有的内置版Action。)
  • 您不需要GCHandle::Alloc(我认为这就是您的意思)。相反,请将_testMethodHandle声明为TestMethodDelegate^(或Action^)。通常,除非您与非托管代码连接,否则您不需要处理GCHandle,并且此代码都是受管理的。

这是我的测试代码:

public ref class BaseyClass
{
public:
    BaseyClass() { this->_testMethodHandle = gcnew Action(this, &BaseyClass::TestMethod); }
    virtual void TestMethod() { Debug::WriteLine("BaseyClass::TestMethod"); }
    Action^ _testMethodHandle;
};

public ref class DerivedClass : BaseyClass
{
public:
    virtual void TestMethod() override { Debug::WriteLine("DerivedClass::TestMethod"); }
};


int main(array<System::String ^> ^args)
{
    BaseyClass^ base = gcnew DerivedClass();
    base->_testMethodHandle();
    return 0;
}

输出:

  

DerivedClass :: TestMethod的