Указатель на абстрактный класс - PullRequest
1 голос
/ 15 сентября 2011

Я пытаюсь обернуть неуправляемый код c ++ с помощью c ++ / cli.В C ++ / cli класс должен быть объявлен abstract , если он имеет все чисто виртуальные функции.Теперь предположим, что у меня есть следующий код на C ++:

class A{
public:
  virtual ~A();
  virtual void foo() = 0;
  virtual void boo() = 0;
  virtual void goo() = 0;
};
inline
A::~A()
{
}

class B
{
public:
  B();
  A* getA() const;
};

inline A* B::getA() const
{
  //do something
  return (A *) //of something;
}

Как указано выше, я могу вернуть A * без каких-либо ошибок.Теперь предположим, что я обертываю приведенный выше код следующим образом:

public ref class manA abstract 
{
public:
  manA(A*);
  virtual ~manA();
  virtual void Foo() = 0;
  virtual void Boo() = 0;
  virtual void Goo() = 0;
private:
  A* m_A;
};

inline
manA::~manA()
{
}

inline
manA::manA(A*)
{
  //data marshalling to convert A* to manA
}

public ref class manB
{
public:
  manB();
  manA ^ GetA();
private:
  B * m_B;
};

inline manB::manB()
{
  m_B = new B;
}

inline manA ^ manB::GetA()
{
  A *value = m_B->getA();
  return gcnew manA(value);
}

Теперь, если я сделаю это, я получу класс, объявленный как 'абстрактный', не может быть создан error.1016 * Есть ли какое-нибудь решение для этого?

Примечание: класс A определяет интерфейс для всех возможных его реализаций.Так, может быть, есть способ определить manA так, чтобы он не был абстрактным и, следовательно, мог быть создан?

Я нашел решение проблемы:

Удалите конструктор из manA и используйте свойство

public:
property A* UnmanagedObject 
{
  void set(A* unmanagedObjPtr)
  {
    //Or other data marshalling
    m_A = (A *)(unmanagedObjPtr);
  }
}

и внутри manB do:

inline manA ^ manB::GetA()
{
  A *value = m_B->getA();
  manA ^ final;
  final->UnmanagedObject  = value;
  return final;
}

Ответы [ 4 ]

1 голос
/ 15 сентября 2011

Написание оболочки не означает написание того же нативного класса. Не делайте manA абстрактным классом, и ваша проблема исчезнет.

public ref class manA abstract 
{
public:
  manA(A*);
  virtual ~manA();
  virtual Foo() { m_A->foo(); } 
  virtual Boo() { m_A->boo(); }
  virtual Goo() { m_A->goo(); }
//Also there should be an error like "Hey, What is the return type of those functions?"
//"virtual void Foo()" or "virtual int Foo()" or something else
private:
  A* m_A;
};
0 голосов
/ 15 сентября 2011

Используйте дженерики.

public ref class manB
{
public:
  manB() 
  {
    m_B = new B();
  }

  generic<T> where T : manA
  manA ^ GetA() 
  {
    A *value = m_B->getA();
    T ^ final = Activator::CreateInstance<T>();
    final->UnmanagedObject  = value;
    return final;
  }
  /* or
  generic<T> where T : manA
  T ^ GetA() 
  {
    A *value = m_B->getA();
    T ^ final = Activator::CreateInstance<T>(); //this requires T has a public default contructor.
    final->UnmanagedObject  = value;
    return final;
  }
  */

  !manB()
  {
    delete m_B; //don't forget to release the native resource
  }
private:
  B * m_B;
};
0 голосов
/ 15 сентября 2011

Я думаю, что проблема в этом

return gcnew manA(value)

вы создаете экземпляр manA, который вы объявили как абстрактный класс ...

0 голосов
/ 15 сентября 2011

inline manB::manB() { m_B = new B; }

Я думаю, что ошибка возникает в этой строке, потому что B является производным от абстрактного класса A и не реализует чистую функцию, определенную в классе A. Поэтому B также является абстрактным классом.Вы никогда не сможете создать экземпляр абстрактного класса B.

...