以下代码显示了一个类,该类从一个接口(interface)私有(private)地继承,该接口(interface)在不授予调用对象友好的情况下访问了其私有(private)函数。我对此感到困惑,但无法真正看到编译器可以提供什么更好的解决方案(代码编译和运行)。为什么这样做?

#include <iostream>

class IVisitor;

class IVisitable
{
public:
    virtual void Accept(IVisitor& visitor) const = 0;
};

class VisitableA;
class VisitableB;

class IVisitor
{
public:

    virtual void Visit(const VisitableA& a) = 0;

    virtual void Visit(const VisitableB& b) = 0;
};

class VisitableA : public IVisitable
{
public:
    virtual void Accept(IVisitor& visitor) const
    {
        visitor.Visit(*this);
    }
};

class VisitableB : public IVisitable
{
public:
    virtual void Accept(IVisitor& visitor) const
    {
        visitor.Visit(*this);
    }
};

class PrivateVisitor : private IVisitor
{
public:
    PrivateVisitor(IVisitable& v)
    {
        v.Accept(*this);
    }

private:

    virtual void Visit(const VisitableA& a)
    {
        std::cout << "I saw A\n";
    }

    virtual void Visit(const VisitableB& b)
    {
        std::cout << "I saw B\n";
    }
};

int main(int argc, char* argv[])
{
VisitableA a;
VisitableB b;

PrivateVisitor p_a(a);
PrivateVisitor p_b(b);
}

最佳答案

仅在编译时检查访问说明符,然后在这些说明符上检查应用它们的对象的静态类型。

PrivateVisitor构造函数内部,*this对象被强制转换为IVisitor。在这种情况下,继承的类型无关紧要,因为我们处于PrivateVisitor类型之内,因此我们拥有完全访问权限。

该对象用于IVisitable对象(VisitableAVisitableB)内部,并调用Visit成员函数。对象的动态类型为PrivateVisitor,而静态类型为IVisitor(引用的类型为IVisitor&)。将根据IVisitor类(其中两个Visit重载都是公共(public)的)检查访问说明符,因此编译器接受该调用。

函数在最终重写器中是私有(private)的事实并不重要,因为访问是通过基类(函数是公共(public)的)执行的。

09-10 03:04
查看更多