Home > Enterprise >  When inheriting a Base class privately, can I declare the Base classes Basse class public?
When inheriting a Base class privately, can I declare the Base classes Basse class public?

Time:11-28

I have a class "SuperBase" with public methods and a class "Base", that derives from SuperBase, also with public methods. I cannot alter these, as they come from an external project.

I want my own class "Derived" to inherit privately from Base, but still keep SuperBase public.

External Code (cannot be changed):

class SuperBase
{
public:
   void printSuperBase() const
   {
      std::cout << "Super Base Class\n";
   }
};

class Base : public SuperBase
{
public:
   void print() const
   {
      std::cout << "Base Class\n";
   }
};

My own code (can be changed):

class Derived: private Base
{
public:
   void print() const
   {
      std::cout << "Derived Class\n";
   }
};

void function(SuperBase const& sb)
{
   sb.printSuperBase();
}


int main() 
{
   Derived D{};
   D.print();    //prints "Derived Class\n"
   function(D);  //cannot access SuperBase, as Base was included privately
}

Note that I cannot override any of the Base class methods, as they are not declared virtual.

Including both, Base and SuperBase does not work as this makes SuperBase ambiguous.

class Derived: private Base, public SuperBase
{
public:
   void print() const
   {
      std::cout << "Derived Class\n";
   }
};

void function(SuperBase const& sb)
{
   sb.printSuperBase();
}


int main() 
{
   Derived D{};
   D.print();    //prints "Derived Class\n"
   function(D);  //base class SuperBase is ambiguous
}

Including Base publicly and declaring it's methods as private does not work either, as I now can pass Derived to functions using Base, that can access all privately declared methods

class Derived: public Base
{
public:
   void print() const
   {
      std::cout << "Derived Class\n";
   }
private:
   using Base::print; //declare base method private to make it inaccessible
};

void function2(Base const& b)
{
   b.print();          //prints "Base Class\n", but shall be inaccessible instead.
   b.printSuperBase();
}


int main() 
{
   Derived D{};
   D.print();    //prints "Derived Class\n"
   function2(D); //D gets passed as Base class, but shall not be allowed
}

CodePudding user response:

Unfortunately, the answer is no.

CodePudding user response:

That heavily depends on whether you depend in type conformance of Derived to Base, what other parts you may want to encompass in your class and how Base itself shadows/overrides SuperBase members, but you may just wrap Base object privately and forward all function calls however you want:

class Derived: public SuperBase
{
    Base imp;
public:
   void print() const
   {
      std::cout << "Derived Class\n";
   }
};

CodePudding user response:

This is not possible, unless SuperBase is a virtual base of Base.

You could introduce a friend function function though that applies the necessary cast to call function:

void function(SuperBase const& sb);

class Derived : private Base
{
public:
    void print() const
    {
        std::cout << "Derived Class\n";
    }

    /**
     * Introduce a overload of function at namespace scope that has access to the conversion to SuperBase
     */
    friend void function(Derived const& derived)
    {
        function(static_cast<SuperBase const&>(derived));
    }
};

void function(SuperBase const& sb)
{
    sb.printSuperBase();
}

CodePudding user response:

You could not actually derive from Base or SuperBase at all but rather use composition and cast operators:

class Derived
{
private:
    Base mBase;

public:
   void print() const
   {
      std::cout << "Derived Class\n";
   }

    operator SuperBase const&() const
    {
        return mBase;
    }

    operator SuperBase&()
    {
        return mBase;
    }
};

https://gcc.godbolt.org/z/bnsY4e5Wz

  • Related