以下代码显示了一个类,该类从一个接口(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
对象(VisitableA
或VisitableB
)内部,并调用Visit
成员函数。对象的动态类型为PrivateVisitor
,而静态类型为IVisitor
(引用的类型为IVisitor&
)。将根据IVisitor
类(其中两个Visit
重载都是公共(public)的)检查访问说明符,因此编译器接受该调用。
函数在最终重写器中是私有(private)的事实并不重要,因为访问是通过基类(函数是公共(public)的)执行的。