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



嵌套类Foo::Utility可以访问另一个嵌套类Foo::Container即使后者是私有的。我试图将此访问权限扩展到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
}
};

是否有正确的方法来实现这一目标,或者这是一个坏主意?

我收到的错误消息是这样的:

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

另外,这是我使用这种有点奇怪的设计的原因: 我想要一个container和一个多态utility,可以同时对容器和Foo执行操作。由于containerutility都只能在Foo的上下文中使用,我将这两个类放入Foo


编辑:我可以将派生的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 */
}
};
};

然而,这引入了一个包装类FooPrint它只出于语法原因而存在,并且(作为一个派生类!(永远不会被实例化。出于这个原因,我不喜欢这种方法,但我在这方面可能大错特错。

访问不是继承的。这在讨论朋友时更常被提出,但在这里也适用。

首先,让我们看看为什么Foo::Utility::action可以访问私有类Foo::Container。实际上,它就在名字中。Foo::Container只能由Foo的成员访问,当你写出他们的限定名称并且该名称以"Foo::"开头时,Foo的成员可以被识别。

相比之下,UtilityPrint不是Foo的成员。(事实上,如果有人可以简单地说"哦,是的,我也是会员!">并访问您的私人信息,那将是一个巨大的安全违规行为。因此,虽然UtilityPrintFoo::Utility有(受保护的(访问权限,但它无法访问Foo::Utility有权访问的所有内容。

如果Foo::Utility希望将其访问扩展到从它派生的类,则需要显式这样做。一种方法是创建别名。

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

这仍然留下了一个问题,即这是否是好的设计。我认为这是一个警告信号,表明某些东西可能会关闭,但不是最终的。这个问题没有足够的背景让我做出这种决定。我只想给你一个指导方针,如果你觉得你正在规避很多语言功能(如私人访问(,那么也许设计需要工作。

我采用了这个解决方案:

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 */
}
};

当使用typedef引入名称FooContainer时,可访问性仅适用于该名称,而不考虑它实际上指的是Foo::Container。这允许所有派生Utility通过命名FooContainer来引用Foo::Container

我相信这也适用于using

最新更新