【问题标题】:How can private inheritance from a visitor interface allow a visitable object to access visit private visit implementations?访问者接口的私有继承如何允许可访问对象访问访问私有访问实现?
【发布时间】:2012-08-16 07:30:26
【问题描述】:

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

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

【问题讨论】:

    标签: c++ inheritance private visitor-pattern


    【解决方案1】:

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

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

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

    函数在最终覆盖器中是 private 的事实并不重要,因为访问是通过基类执行的,其中函数是 public。 p>

    【讨论】:

      【解决方案2】:

      这里重要的私人是这个:

      PrivateVisitor : private IVisitor
      

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-20
          • 2018-04-21
          • 2012-01-04
          • 2020-02-11
          • 1970-01-01
          • 2013-02-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多