0

我正在尝试在我的本机库和我的 C# 客户端代码之间架起一座桥梁。

为此,我有一个名为“IHasManagedWrapper”的界面:

#ifndef IHASMANAGEDWRAPPER_H_
#define IHASMANAGEDWRAPPER_H_

template <typename T>
class IHasManagedWrapper
{
public:
    virtual T^ CreateManagedWrapper() = 0;
};

#endif

然后,为了测试返回的 CLI 类型的多态性,我创建了两个本地类 Parent 和 Child,其中 Child 继承自 Parent:

家长:

#ifndef PARENT_H_
#define PARENT_H_

#include "IHasManagedWrapper.h"

ref class CLIParent;

class Parent : public IHasManagedWrapper<CLIParent>
{
public:
    Parent();
    ~Parent();

    virtual char* GetName();

    virtual CLIParent^ CreateManagedWrapper();
};

#endif

孩子:

#ifndef CHILD_H_
#define CHILD_H_

#include "Parent.h"
#include "IHasManagedWrapper.h"

ref class CLIChild;

class Child : public Parent, IHasManagedWrapper<CLIChild> // uh-oh...
{
public:
    char* GetName();

    CLIChild^ CreateManagedWrapper();
}; // error C2555: 'Child::CreateManagedWrapper': overriding virtual function return type differs and is not covariant from 'Parent::CreateManagedWrapper'


#endif

我通过将“CLIChild”更改为“CLIParent”并从 IHasManagedWrapper 中删除 CLIChild 的继承来使其工作,但这意味着每次我调用 Child->CreateManagedWrapper() 时,我都会得到一个 CLIParent 对象,然后我需要手动强制转换为 CLIChild 对象。

IE

CLIChild^ child = safe_cast<CLIChild^>(pChild->GetManagedWrapper()); // pChild->GetManagedWrapper() returns a CLIParent^ object

虽然这还不错,但有没有办法让 CLIChild->CreateManagedWrapper() 返回一个 CLIChild 对象,同时保留 IHasManagedWrapper 接口?

谢谢!

4

1 回答 1

1

您可以通过将重载的虚拟方法的主体转移到特定方法(Child::CreateManagedWrapperChild例如Child. 重载的虚拟方法将简单地调用特定方法并将其结果向上转换CLIParent以匹配正确的方法签名。

class Child : public Parent {
public:
    char* GetName();
    CLIParent^ CreateManagedWrapper() { return CreateManagedWrapperChild(); }
    CLIChild^ CreateManagedWrapperChild(); // actual code in this method
};

这看起来不像您希望编写的那样干净,但它已被编译器接受,并且在实践中应该只适用于一级继承。对于不止一个,您还必须创建CreateManagedWrapperChildvirtual ,以相同的方式重载它 say GrandChild,并重载原始虚拟方法以直接调用该 CreateManagedWrapperGrandChild方法,以避免嵌套的虚拟调用。

但是,对于大型继承树,这种技术不是很实用,因为特定虚方法的爆炸式增长。

于 2013-06-20T09:16:49.883 回答