Search code examples
.netpointersinheritancec++-climixed-mode

Inheritance between managed and unmanaged classes


Hello I have a question regarding inheritance in a project mixing C++ and C#. So i have a C++/CLI layer doing the stuff inbetween. In C++ I have 2 structures :

public Class A : 
{
public :
 A(){*a = new int(); *a = 0;}
 void f1(){*a = 10};
 int geta(){return *a};
private :
 int *a;
}

public Class B : public A
{
public :
 B(){*b = new int(); *b = 0;}
 void f2(){*b = 5; *a = 10};
 int getb(){return *b};
 int getinheriteda(){return *a;};
private : 
 int *b
}

Then in C++/CLI, I have the 2 sames classes in their managed version. Each one owns a pointer to the unmanaged C++ Class.

public ref Class ANet : 
{
public :
 ANet(){ un_a = new A();}
 ~ANet(){ this->!ANet();}
 !ANet(){ delete un_a;}
 void f1Net(){ un_a->f1();}
 int getanet(){return un_a->geta();}
private:
 A *un_a; //Pointer to the unmanaged A
}

Version 1 :

public ref Class BNet : public Class ANet:
{
public :
 BNet(){ un_b= new B();}
 ~BNet(){ this->!BNet();}
 !BNet(){ delete un_b;}
 void f2Net(){ ((B*)un_a)->f2();}
 int getbnet(){return un_b->getb();}
 int getinheriteda(){return un_b->getinheriteda();};
private:
 B *un_b; //Pointer to the unmanaged B
}

Version 2:

public ref Class BNet : public Class ANet:
{
 BNet(){ un_a = new B();}
 ~BNet(){ this->!BNet();}
 !BNet(){ delete un_a;}
 void f2Net(){ ((B*)un_a)->f2();}
 int getbnet(){return((B*)un_a)->getb();}
 int getinheriteda(){return ((B*)un_a)->getinheriteda();};
private:
 //No pointer, use inherited un_a;
}

Problems :

Version 1 : If I get instance of B, then I have two pointer (un_b and inherited un_a) so each pointer got it unmanaged class resulting in inconsistency.

Version 2 : If I get instance of B, then I have one pointer, but created two times resulting in inconsistency

How I can implement a managed C++/CLI structures that could wrap those 2 unmanaged classes. Any ideas ?


Solution

  • C++ way would be to have separate constructor in ANet that accepts unmanaged pointer:

    public ref class ANet
    {
    ...
    protected:
        ANet(A* a) : un_a(a) { ... }
    ...
    
    public ref class BNet : public ANet
    {
    public:
       BNet() : ANet(new B()) { ... }
    ...
    

    In .Net you can also call a virtual method in ANet constructor to create unmanaged instance and override it if needed:

    public ref class ANet
    {
    public:
        ANet() { un_a = CreateUnmanagedInstance(); }
    ...
    protected:
       virtual A* CreateUnmanagedInstance() { return new A(); }
    
    public ref class BNet : public ANet
    {
    ...
    protected:
       virtual A* CreateUnmanagedInstance() override { return new B(); }
    ...
    

    But since this approach does not work with native C++ classes it may be considered too tricky and harmful.