c++thisprivate-inheritance

Why does C++ allow this pointer polymorphism of private parent?


If I inherit a derived class privately from a base class, I cannot get the polymorphism of the inhritetted class.

But I can get the polymorphism of 'this' pointer inside the derived class.

I'm very curious about why 'this' pointer is allowed to polymorphism to its private parent, however, a pointer outside of the class is not.

Thanks in advance!

#include <iostream>

class Shape
{
public:
    virtual void say() const = 0;
    virtual void who()
    {
        std::cout << "Shape" << std::endl;
    }
    void whoAmI() {
        this->who();
    }
};

class Squire : private Shape
{
public:
    virtual void say() const
    {
        std::cout << "Squire" << std::endl;
    }
    
    void doSay()
    {
        // why this pointer to Shape type is allowed in class?
        privateSay(this);
    }
    
private:
    void privateSay(Shape* s)
    {
        s->say();
    }
};

void say(Shape* s)
{
    s->say();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    
    Squire* s = new Squire();
    // allowed
    s->doSay();
    
    // not allowd, compile errors
    // Cannot cast 'Squire' to its private base class 'Shape'
    say(s);
    
    return 0;
}

=========

Edit to clarify. Thanks for all the answers. To clarify my question, I think if C++ allows this behavior, mybe it violates the encapsulation a little.

A clearer case:

#include <iostream>

class Base
{
public:
    void baseFunc() const
    {
        std::cout << "baseFunc" << std::endl;
    }
};

class Worker
{
public:
    Worker(Base *pBase)
    {
        base_ = pBase;
    }
    
    void breakFunc() const
    {
        base_->baseFunc();
    }
private:
    Base *base_;
};

class Derived : private Base
{
public:
    void init()
    {
        worker_ = new Worker(this);
    }
    
    Worker* getWorker()
    {
        return worker_;
    }

private:
    Worker *worker_;
};

int main()
{
    Derived derived;
    derived.init();
    
    
    Worker *worker = derived.getWorker();
    worker->breakFunc();
}

The object of Base class only exisits in the object of Derived class as the parent object part, however, the Derived class inheritents Base class privately, which means the object of the Derived class has-an object of the Base class, privately.

The code above violates the encapsulation rule of the Derived class, however, even no warnning is given during compilation.

In my opinion, an explicit cast should be used under the circumstances,or an warning should be given during compilation.


Solution

  • The question asked here is why a base class is accessible when privately inherited.
    The answer is rather simple: Because base classes are always visible to inherited regardless of the type of inheritance.

    You can static_cast to a base class when the base is visible within the context.

    
    class base
    {
    };
    
    class inherited : base
    {
    public:
    
    void foo()
    {
        // works, base is visible within the method.
        auto pBase = static_cast<base*>(this);
    }
    };
    
    int main() {
        inherited i{};
        // auto pBase = static_cast<base*>(&i); // won't compile, base is not visible
        return 0;
    }