更改派生类中的函数访问模式
考虑以下代码片段:
struct Base
{
virtual ~Base() {}
virtual void Foo() const = 0; // Public
};
class Child : public Base
{
virtual void Foo() const {} // Private
};
int main()
{
Child child;
child.Foo(); // Won't work. Foo is private in this context.
static_cast<Base&> (child).Foo(); // Okay. Foo is public in this context.
}
这是合法的 C++ 吗? “This”正在更改派生类中虚拟函数的访问模式。
Consider the following snippet:
struct Base
{
virtual ~Base() {}
virtual void Foo() const = 0; // Public
};
class Child : public Base
{
virtual void Foo() const {} // Private
};
int main()
{
Child child;
child.Foo(); // Won't work. Foo is private in this context.
static_cast<Base&> (child).Foo(); // Okay. Foo is public in this context.
}
Is this legal C++? "This" being changing the virtual function's access mode in the derived class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是合法的 C++,§11.6/1 说:
正如您所指出的,
Child::Foo()
因此仍然可以通过基类访问,这在大多数情况下是不需要的:基本上,您在表达式中引用的声明决定了访问模式 - 但虚拟函数破坏了这一点,作为另一个函数,那么实际上可以调用指定的函数。
This is legal C++, §11.6/1 says:
As you noted,
Child::Foo()
is thus still accessible via the base class, which is in most cases undesired:Basically, the declaration you refer to in the expression dictates the access mode - but virtual functions undermine that as another function then the named one may actually be invoked.
是的,更改派生类中的访问模式是合法的。
这在形式上相似,但在意图上非虚拟接口 习惯用法。 此处给出了一些基本原理:
至于为什么您实际上会在基类中创建一些
public
内容,但在没有private
或protected
继承的情况下在派生中创建private
内容,这是超出了范围我。Yes, changing the access mode in derived classes is legal.
This is similar in form but different in intent to the Non-Virtual Interface idiom. Some rationale is given here:
As to why you would actually make something
public
in base butprivate
in derived withoutprivate
orprotected
inheritance is beyond me.它是完全合法的C++。您只需在 Child 类中定义一个新方法。
现在它是否做你想要它做的事情,这是另一个问题。
我相信访问模式不是方法签名的一部分,这意味着调用 Base 的 Foo 虚拟方法最终会调用 Child 的 Foo 方法。
所以结论是:它是合法的 c++,并且按照您期望的方式工作。
我没有考虑
child.Foo();
行,它可以'不起作用,因为毫无疑问它正在尝试访问 Child 的私有 Foo() 方法。It is perfectly legal C++. You are simply defining a new method in Child class.
Now does it do what you want it to do, that's an other question.
I believe the access mode is not part of the method signature, which means that calling Base's Foo virtual method does eventually call Child's Foo method.
So here's the conclusion : it is legal c++ and it works the way you'd expect.
I am not taking into consideration the line
child.Foo();
which can't work because there is no doubt it is trying to access Child's private Foo() method.似乎编译并调用了正确的方法。
请记住,访问说明符是为了帮助有纪律的程序员,而不是为了不惜一切代价阻止所有规避它的尝试。
在这种特殊情况下,Child 没有义务将重写的虚拟函数设为私有:它不是应该实现 Base 的公共接口,因此“is-a”关系成立吗? (如果您没有使用公共继承,这意味着“Child is a Base”,您的技巧将不起作用。)
It seems to compile and call the right method.
Remember that access specifiers are there to help a disciplined programmer, not to prevent all attempts to circumvent it at all costs.
In this particular case, Child has no business making the overridden virtual function private: isn't it supposed to implement the public interface of Base, so the "is-a" relationship holds? (If you didn't use public inheritance, which means "Child is a Base", your trick wouldn't work.)