更改派生类中的函数访问模式

发布于 2024-08-19 09:39:55 字数 423 浏览 4 评论 0原文

考虑以下代码片段:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你是年少的欢喜 2024-08-26 09:39:55

这是合法的 C++,§11.6/1 说:

在呼叫点检查访问权限
使用所用表达式的类型
来表示对象
成员函数被调用(B*在
上面的例子)。的访问
类中的成员函数,其中
它被定义(示例中的 D
上述)通常是未知的。

正如您所指出的, Child::Foo() 因此仍然可以通过基类访问,这在大多数情况下是不需要的:

 Child* c = new Child;
 Base* b = c;
 c->Foo(); // doesn't work, Child::Foo() is private
 b->Foo(); // works, calls Child::Foo()

基本上,您在表达式中引用的声明决定了访问模式 - 但虚拟函数破坏了这一点,作为另一个函数,那么实际上可以调用指定的函数。

This is legal C++, §11.6/1 says:

Access is checked at the call point
using the type of the expression used
to denote the object for which the
member function is called (B* in the
example above). The access of the
member function in the class in which
it was defined (D in the example
above) is in general not known.

As you noted, Child::Foo() is thus still accessible via the base class, which is in most cases undesired:

 Child* c = new Child;
 Base* b = c;
 c->Foo(); // doesn't work, Child::Foo() is private
 b->Foo(); // works, calls Child::Foo()

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.

我ぃ本無心為│何有愛 2024-08-26 09:39:55

是的,更改派生类中的访问模式是合法的。

这在形式上相似,但在意图上非虚拟接口 习惯用法。 此处给出了一些基本原理:

重点是虚拟函数的存在是为了允许定制;除非它们还需要从派生类的代码中直接调用,否则不需要将它们设置为私有。

至于为什么您实际上会在基类中创建一些 public 内容,但在没有 privateprotected 继承的情况下在派生中创建 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:

The point is that virtual functions exist to allow customization; unless they also need to be invoked directly from within derived classes' code, there's no need to ever make them anything but private.

As to why you would actually make something public in base but private in derived without private or protected inheritance is beyond me.

独闯女儿国 2024-08-26 09:39:55

它是完全合法的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.

无悔心 2024-08-26 09:39:55

似乎编译并调用了正确的方法。

请记住,访问说明符是为了帮助有纪律的程序员,而不是为了不惜一切代价阻止所有规避它的尝试。

在这种特殊情况下,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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文