无法从多态嵌套 classes 访问包含 class 的成员
Unable to access members of including class from a polymorphic nested classes
嵌套的 class Foo::Utility
可以访问另一个嵌套的 class 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
和一个对容器和 Foo
都起作用的多态 utility
。由于 container
和 utility
都只会在 Foo
的上下文中使用,我将两个 class 放入 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 */
}
};
};
然而,这引入了一个包装器 class FooPrint
,它仅出于句法原因而存在,并且(作为派生的 class!)永远不会被实例化。由于这个原因,我不喜欢这种方法,但在这方面我可能会大错特错。
访问权限不继承。这在讨论friends时更常被提及,但在这里也适用。
先来看看为什么Foo::Utility::action
可以访问私有classFoo::Container
。实际上,它就在名字中。 Foo::Container
只能被Foo
的成员访问,而Foo
的成员只要写出以“Foo::
”开头的限定名即可识别。
相比之下,UtilityPrint
不是 Foo
的成员。 (事实上 ,如果有人可以简单地说 "oh, yeah, I'm a member too!" 并获得您的私人信息,那将是一个巨大的安全违规行为。)所以虽然 UtilityPrint
已经(受保护) 访问 Foo::Utility
,它无法访问 Foo::Utility
可以访问的所有内容。
如果 Foo::Utility
希望扩展对从它派生的 classes 的访问,则需要明确地这样做。一种方法是创建一个别名。
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
};
这是否是一个好的设计仍然悬而未决。我会认为这是一个警告标志,表明可能存在某些问题,但并非最终如此。这个问题没有足够的背景让我做出这样的决定。我只想给你一个指导方针,如果你觉得你正在规避很多语言功能(比如私人访问),那么也许设计需要改进。
我采纳了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 */
}
};
当使用 typedef
引入名称 FooContainer
时,可访问性仅应用于该名称,而不考虑它实际上指的是 Foo::Container
。这允许所有派生的 Utility
通过命名 FooContainer
.
来引用 Foo::Container
我相信这也适用于 using
嵌套的 class Foo::Utility
可以访问另一个嵌套的 class 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
和一个对容器和 Foo
都起作用的多态 utility
。由于 container
和 utility
都只会在 Foo
的上下文中使用,我将两个 class 放入 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 */
}
};
};
然而,这引入了一个包装器 class FooPrint
,它仅出于句法原因而存在,并且(作为派生的 class!)永远不会被实例化。由于这个原因,我不喜欢这种方法,但在这方面我可能会大错特错。
访问权限不继承。这在讨论friends时更常被提及,但在这里也适用。
先来看看为什么Foo::Utility::action
可以访问私有classFoo::Container
。实际上,它就在名字中。 Foo::Container
只能被Foo
的成员访问,而Foo
的成员只要写出以“Foo::
”开头的限定名即可识别。
相比之下,UtilityPrint
不是 Foo
的成员。 (事实上 ,如果有人可以简单地说 "oh, yeah, I'm a member too!" 并获得您的私人信息,那将是一个巨大的安全违规行为。)所以虽然 UtilityPrint
已经(受保护) 访问 Foo::Utility
,它无法访问 Foo::Utility
可以访问的所有内容。
如果 Foo::Utility
希望扩展对从它派生的 classes 的访问,则需要明确地这样做。一种方法是创建一个别名。
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
};
这是否是一个好的设计仍然悬而未决。我会认为这是一个警告标志,表明可能存在某些问题,但并非最终如此。这个问题没有足够的背景让我做出这样的决定。我只想给你一个指导方针,如果你觉得你正在规避很多语言功能(比如私人访问),那么也许设计需要改进。
我采纳了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 */
}
};
当使用 typedef
引入名称 FooContainer
时,可访问性仅应用于该名称,而不考虑它实际上指的是 Foo::Container
。这允许所有派生的 Utility
通过命名 FooContainer
.
Foo::Container
我相信这也适用于 using