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