嵌套类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
执行操作。由于container
和utility
都只能在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
的成员。(事实上,如果有人可以简单地说"哦,是的,我也是会员!">并访问您的私人信息,那将是一个巨大的安全违规行为。因此,虽然UtilityPrint
对Foo::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