Вызов переопределенного метода производного собственного класса через оболочки (производные управляемые классы) в C ++ / CLI - PullRequest
1 голос
/ 09 октября 2011

У меня сказка о 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 (), который оборачивает NativeExecute () в NativeParentA. Когда вызывается этот метод, все работает гладко.

NativeChildB, ManagedChildB переопределяют ManagedExecute () для предоставления своих собственных реализаций, с помощью обертки ManagedChildA :: ManagedExecute (), NativeChildA :: NativeExecute () и ManagedChildB :: ManagedExecute (), обертывания NativeChildB :: NativeExecute ().

Когда, например, вызывается переопределенный ManagedExecute () ManagedChildA, NativeChildA :: NativeExecute () вызывается, хотя и с ошибкой System.AccessViolation. То есть указатель на исходный родительский объект 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
}

1 Ответ

1 голос
/ 09 октября 2011

Фрагмент очень низкого качества, он усеян нескомпилируемым кодом.Нет репро, как только я исправил все ошибки.

#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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...