我正在尝试在本机库和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对象。



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


尽管还算不错,但是有没有一种方法可以使CLIChild-> CreateManagedWrapper()在保留IHasManagedWrapper接口的同时返回CLIChild对象?

谢谢!

最佳答案

您可以通过将重载的虚拟方法的主体转移到特定方法(例如Child::CreateManagedWrapperChild)中,然后在知道要处理Child时调用该特定方法来解决此问题。重载的虚拟方法将只调用特定方法并将其结果上载到CLIParent以匹配正确的方法签名。

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


它看起来不像您希望编写的那样干净,但是它已被编译器接受,并且在实践中仅对一级继承有效。对于多个对象,您还必须使CreateManagedWrapperChild虚拟化,以相同的方式重载GrandChild,并重载原始虚拟方法以直接调用CreateManagedWrapperGrandChild方法,以避免嵌套的虚拟调用。

但是,对于大型的继承树,由于特定的虚拟方法的激增,该技术不是很实用。

关于c++ - 与C++/CLI和模板的协方差,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17204835/

10-12 00:43