简体   繁体   English

无法从多态嵌套类访问包括 class 的成员

[英]Unable to access members of including class from a polymorphic nested classes

A nested class Foo::Utility has access to another nested class Foo::Container even if the later is private.一个嵌套的 class Foo::Utility可以访问另一个嵌套的 class Foo::Container ,即使后者是私有的。 I am trying to extend this access to a polymorphic version UtilityPrint of Foo::Utility without success:我试图将此访问扩展到Foo::Utility的多态版本UtilityPrint ,但没有成功:

class Foo {
private:
  class Container {};

public:
  class Utility {
  public:
    virtual void action(Container &) = 0;
    // works even if Container is private
  };

  Container container;
  Utility * utility;

  Foo(Utility * utility): container(), utility(utility) {};

  void performAction() {
    utility -> action(container);
  }
};

// polymorphic nested class
// failed attempt
class UtilityPrint : Foo::Utility {
public:
  virtual void action(Foo::Container &) {
    /* Implementation */

    // this does not work, because Foo::Container is private
  }
};

Is there a correct way to achieve this, or is this a bad idea to begin with?有没有正确的方法来实现这一点,或者这是一个坏主意?

The error message I get is this:我得到的错误信息是这样的:

error: ‘class Foo::Container’ is private
   class Container {};
         ^
error: within this context
   virtual void action(Foo::Container &) {

Also, Here is my reason for using this somewhat weird design: I wanted a container and a polymorphic utility that does things to both the container and Foo .另外,这是我使用这种有点奇怪的设计的原因:我想要一个container和一个多态utility ,它可以同时对容器和Foo执行操作。 Since both container and utility would only be used within the context of Foo , I put the two classes into Foo .由于containerutility都只能在Foo的上下文中使用,因此我将这两个类放入Foo中。


EDIT: I can wrap the derived Utility in a derived Foo , and the code compiles:编辑:我可以将派生的Utility包装在派生的Foo中,并且代码编译:

class Foo {
protected:
  class Container {};

public:
  class Utility {
  public:
    virtual void action(Container &) = 0;
  };

  Container container;
  Utility * utility;

  Foo(Utility * utility): container(), utility(utility) {};

  void performAction() {
    utility -> action(container);
  }
};

class FooPrint : public Foo {

public:
  class Utility : Foo::Utility {
  public:
    virtual void action(Foo::Container &) {
      /* Implementation */
    }
  };

};

This however introduces a wrapper class FooPrint which exists only for syntactic reasons and is (being a derived class.) never meant to be instantiated, I don't like this approach for this reason.然而,这引入了一个包装器 class FooPrint ,它仅出于句法原因而存在,并且(作为派生的 class。)从未打算实例化,因此我不喜欢这种方法。 but I can be very wrong on this regard.但在这方面我可能是非常错误的。

Access is not inherited.访问不被继承。 This is more often brought up when discussing friends , but it applies here as well.这在讨论朋友时经常被提起,但在这里也适用。

First, let's look at why Foo::Utility::action can access the private class Foo::Container .首先,让我们看看为什么Foo::Utility::action可以访问私有的 class Foo::Container Actually, it's right there in the names.实际上,它就在名称中。 The Foo::Container can only be accessed by members of Foo , and members of Foo can be recognized when you write out their qualified names and that name starts with " Foo:: ". Foo::Container只能由Foo的成员访问,并且Foo的成员可以在您写出其限定名称并且该名称以“ Foo:: ”开头时被识别。

In contrast, UtilityPrint is not a member of Foo .相反, UtilityPrint不是Foo的成员。 (In fact, it would be a huge security violation if someone could simply say "oh, yeah, I'm a member too!" and get access to your private information.) So while UtilityPrint has (protected) access to Foo::Utility , it does not have access to everything to which Foo::Utility has access. (事实上,如果有人可以简单地说“哦,是的,我也是会员!”并访问您的私人信息,那将是一个巨大的安全违规。)因此,虽然UtilityPrint具有(受保护)访问Foo::Utility ,它无法访问Foo::Utility可以访问的所有内容。

If Foo::Utility desires to extend its access to classes derived from it, it would need to explicitly do so.如果Foo::Utility希望扩展其对派生自它的类的访问,则需要显式地这样做。 One way to do this is by creating an alias.一种方法是创建别名。

class Utility {
  protected:
    using Container = Foo::Container;  // Derived classes can access this.
  public:
    virtual void action(Container &) = 0;
    virtual ~Utility() {}  // <-- remember to properly support polymorphism 
};

That still leaves open the question of whether or not this is good design.这仍然留下了这是否是好的设计的问题。 I would consider this a warning flag that something might be off, but not conclusively so.我会认为这是一个警告标志,表明某些事情可能已关闭,但并非最终如此。 The question does not have enough context for me to make this sort of call.这个问题没有足够的背景让我做出这种呼吁。 I would just give you the guideline that if you feel like you are circumventing a lot of language features (like private access), then maybe the design needs work.我只想给你一个指导方针,如果你觉得你正在绕过很多语言特性(比如私人访问),那么也许设计需要工作。

I adopted this solution :我采用了这个解决方案

class Foo {
protected:
  class Container {};

public:
  class Utility {
  protected:
    typedef Container FooContainer;

  public:
    virtual void action(Container &) = 0;
  };

  Container container;
  Utility * utility;

  Foo(Utility * utility): container(), utility(utility) {};

  void performAction() {
    utility -> action(container);
  }
};

class UtilityPrint : Foo::Utility {
public:
  virtual void action(FooContainer &) {
    /* implementation */
  }
};

When the name FooContainer is introduced using typedef , accessibility is applied to that name only, with no regard of it actually referring to Foo::Container .当使用typedef引入名称FooContainer时,可访问性仅应用于该名称,而不考虑它实际上指的是Foo::Container This allows all derived Utility to reference Foo::Container by naming FooContainer .这允许所有派生的Utility通过命名FooContainer来引用Foo::Container

I believe this also applies to using我相信这也适用于using

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM