在派生类中更改功能访问模式

hlx*_*6sk 26 c++ inheritance access-modifiers

请考虑以下代码段:

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.
}
Run Code Online (Sandbox Code Playgroud)

这是合法的C++吗?"这"正在改变派生类中的虚函数访问模式.

Geo*_*che 21

这是合法的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()
Run Code Online (Sandbox Code Playgroud)

基本上,您在表达式中引用的声明指示访问模式 - 但虚函数破坏了作为另一个函数,然后实际上可以调用命名的函数.

  • @ThomasMcLeod:同一行中的评论说哪个;) (2认同)

MSN*_*MSN 15

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

这是类似的形式,但不同的意图的非虚拟接口惯用法.这里给出一些基本原理:

关键是存在虚拟功能以允许定制; 除非它们还需要直接从派生类的代码中调用,否则不需要将它们变成私有的.

至于为什么你实际上会public在基础上创造一些东西,但是private在没有privateprotected继承的情况下衍生出来是超出我的

  • 这与NVI完全相反:基类的功能是公共+虚拟,但在NVI中它是私有+虚拟,而调用它的公共功能是非虚拟的. (5认同)

Ben*_*oît 5

这是完全合法的C++.您只是在Child类中定义一个新方法.

现在它做了你想做的事情,这是另一个问题.我认为访问模式不是方法签名的一部分,这意味着调用Base的Foo虚方法最终会调用Child的Foo方法.

所以这里得出结论:它是合法的c ++,它的工作方式与你期望的一样.

我没有考虑child.Foo();无法工作的行,因为毫无疑问它正在尝试访问Child的私有Foo()方法.