0

如果我从基类私下继承派生类,我无法获得继承类的多态性。

但是我可以在派生类中获得“this”指针的多态性。

我很好奇为什么允许'this'指针多态到它的私有父级,但是,类外的指针却不允许。

提前致谢!

#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;
}

=========

编辑以澄清。感谢所有的答案。为了澄清我的问题,我认为如果 C++ 允许这种行为,我可能会稍微违反封装

一个更清晰的案例:

#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();
}

Base 类的对象只作为父对象部分存在于 Derived 类的对象中,而 Derived 类的继承者是私有的 Base 类,也就是说 Derived 类对象有一个基类的对象,私有的。

上面的代码违反了Derived 类的封装规则,但是在编译过程中甚至没有给出警告。

我认为在这种情况下应该使用显式强制转换,或者在编译时给出警告。

4

2 回答 2

2

这里提出的问题是为什么私有继承时可以访问基类
答案很简单:因为无论继承的类型如何,基类对继承都是可见的

static_cast当基类在上下文中可见时,您可以添加到基类。


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;
}
于 2021-08-21T11:03:55.550 回答
1

私有继承意味着基类中的符号public和符号都成为派生类的符号。派生类无法访问基类的符号。除了仍然可以覆盖的私有虚拟方法。protectedprivateprivate

this指针,或者一般Class* ptr在类内部使用,可以访问类的私有字段。

由于该符号Shape::say在 中是公共的,因此它在(顺便说一句,您是说 Square 吗?)Shape中变为私有。Squire这可以防止它被公众使用,但不能被this. 由于虚拟规则,这“私有化”了整个覆盖方法链。

void Squire::privateSay(Shape* s)
{
    // Works because `Shape::say` is a public symbol of Shape -> private symbol of Squire and `this` can access private symbols.
    s->say();
}
void say(Shape* s)
{
    // Shape::say is a private symbol, obviously cannot be called.
    s->say();
}

如果存在私有方法,即使通过任何Shape::foo()方法都无法访问它。thisSquire

于 2021-08-21T10:53:11.130 回答