1

下面的代码显示了一个类,该类从一个接口私有继承,该接口在不授予调用对象友谊的情况下访问其私有函数。我对此感到困惑,但真的看不出编译器能提出什么更好的解决方案(代码编译和运行)。为什么这行得通?

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

3 回答 3

4

访问说明符仅在编译时检查,并在其中检查应用它们的对象的静态类型。

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

该对象在IVisitable对象(VisitableAVisitableB)内部使用并Visit调用成员函数。虽然对象的动态类型是PrivateVisitor,但静态类型是IVisitor(引用类型是IVisitor&)。IVisitor针对两个Visit重载都是public的类检查访问说明符,因此编译器接受调用。

函数在最终覆盖器中是私有的这一事实并不重要,因为访问是通过基类执行的,其中函数是public

于 2012-08-20T23:51:03.260 回答
1

这里重要的私人是这个:

PrivateVisitor : private IVisitor

幸运的是,将 PrivateVisitor 强制转换为 IVisitor 的唯一地方是构造函数:

PrivateVisitor::PrivateVisitor(IVisitable& v)
{
    v.Accept(*this);
}

并且构造函数可以访问该类的私有基。

于 2012-08-20T23:38:05.707 回答
0

private 在类范围内,而不是在对象范围内。

于 2012-08-20T23:35:00.897 回答