在C ++ / CLI中通过包装器(派生的托管类)调用派生本机类的重写方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C ++ / CLI中通过包装器(派生的托管类)调用派生本机类的重写方法相关的知识,希望对你有一定的参考价值。
我有6个班级的故事:3个托管和3个原生。 3个管理类是ManagedChildA
,ManagedChildB
和ManagedParent
。
ManagedChildA
,ManagedChildB
都继承自ManagedParentA
。
3个本地课程是NativeChildA
,NativeChildB
和NativeParent
。
NativeChildA
,NativeChildB
都继承自NativeParentA
。
此外,ManagedChildA
包裹NativeChildB
,ManagedChildB
包裹ManagedChildB
和ManagedParentA
包裹NativeParentA
。
现在这个故事发出了错误:
ManagedParentA有一个名为ManagedExecute()的方法,它包装了NativeParentA的NativeExecute()。调用此方法时,一切都顺利进行。
NativeChildB,ManagedChildB重写ManagedExecute()以提供自己的实现,ManagedChildA :: ManagedExecute()包装NativeChildA :: NativeExecute()和ManagedChildB :: ManagedExecute()包装NativeChildB :: NativeExecute()。
例如,当调用ManagedChildA的重写ManagedExecute()时,尽管出现System.AccessViolation错误,但仍会调用NativeChildA :: NativeExecute()。也就是说,无法找到指向NativeChildA原始父级的指针。
我猜指针已从其原始地址移开。我在互联网上阅读,我必须指针防止垃圾收集器(GC)移动内存,但我不知道要固定什么,因为异常会在本机级别抛出。任何有用的提示?
例:
//C++ -native classes
class NativeFoo
{
public:
NativeFoo(): tested(true){}
virtual void execute()
{
std::cout << "Native Foo" << std::endl;
}
protected:
bool tested;
};
class NativeBarA :NativeFoo
{
public:
NativeBarA(): NativeFoo(){}
void execute()
{
std::cout << "Native Bar A" << std::endl;
}
};
class NativeBarB : public NativeFoo
{
public:
NativeBarB() :NativeFoo(){}
void execute()
{
std::cout << "Native Bar B" << std::endl;
}
};
//CLI interface
public interface class IExecutable
{
public:
Execute();
}
//C++-CLI classes
public ref class ManagedFoo: public IExecutable
{
private:
NativeFoo* impl;
public:
ManagedFoo(): impl(NULL)
{
impl = new NativeFoo();
}
void __clrcall Execute()
{
impl->execute();
}
};
public ref class ManagedBarA: public ManagedFoo
{
private:
NativeBarA* impl;
public:
ManagedBarA(): ManagedFoo(), impl(NULL)
{
impl = new NativeBarA();
}
void __clrcall Execute() override
{
impl->execute();
}
};
public ref class ManagedBarB: public ManagedFoo
{
private:
NativeBarB* impl;
public:
ManagedBarB(): ManagedFoo(), impl(NULL)
{
impl = new NativeBarB();
}
void __clrcall Execute() override
{
impl->execute();
}
};
//Calling code
[STAThread]
static void Main()
{
ManagedFoo^ mfoo = gcnew ManagedFoo();
ManagedBarA mbarA = gcnew ManagedBarA();
ManagedBarB mbarB = gcnew ManagedBarB();
mfoo->Execute(); //OK
mbarA->Execute(); //Error. Debugger sees value of tested as false
mBarB->Execute(); //Error
}
该代码片段质量非常低,充斥着无法编译的代码。一旦我解决了所有的错误,就没有责任了。
#include "stdafx.h"
#include <iostream>
using namespace System;
//C++ -native classes
class NativeFoo
{
public:
NativeFoo(): tested(true){}
virtual void execute()
{
std::cout << "Native Foo" << std::endl;
}
protected:
bool tested;
};
class NativeBarA :NativeFoo
{
public:
NativeBarA(): NativeFoo(){}
void execute()
{
std::cout << "Native Bar A" << std::endl;
}
};
class NativeBarB : public NativeFoo
{
public:
NativeBarB() :NativeFoo(){}
void execute()
{
std::cout << "Native Bar B" << std::endl;
}
};
//CLI interface
public interface class IExecutable
{
public:
void Execute();
};
//C++-CLI classes
public ref class ManagedFoo: public IExecutable
{
private:
NativeFoo* impl;
public:
ManagedFoo(): impl(NULL)
{
impl = new NativeFoo();
}
virtual void Execute()
{
impl->execute();
}
};
public ref class ManagedBarA: public ManagedFoo
{
private:
NativeBarA* impl;
public:
ManagedBarA(): ManagedFoo(), impl(NULL)
{
impl = new NativeBarA();
}
virtual void __clrcall Execute() override
{
impl->execute();
}
};
public ref class ManagedBarB: public ManagedFoo
{
private:
NativeBarB* impl;
public:
ManagedBarB(): ManagedFoo(), impl(NULL)
{
impl = new NativeBarB();
}
virtual void __clrcall Execute() override
{
impl->execute();
}
};
//Calling code
[STAThread]
int main(array<System::String ^> ^args)
{
ManagedFoo^ mfoo = gcnew ManagedFoo();
ManagedBarA^ mbarA = gcnew ManagedBarA();
ManagedBarB^ mbarB = gcnew ManagedBarB();
mfoo->Execute(); //OK
mbarA->Execute(); //Fine
mbarB->Execute(); //Fine
}
以上是关于在C ++ / CLI中通过包装器(派生的托管类)调用派生本机类的重写方法的主要内容,如果未能解决你的问题,请参考以下文章
通过 CLI 包装器在非托管 C++ 中使用 C#.NET Winform - 需要线程?
在Visual Studio 2010中将Native / C ++ DLL链接到托管C ++ / CLI包装器