提问者:小点点

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


请考虑以下代码段:

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”正在更改派生类中虚函数的访问模式。


共3个答案

匿名用户

是的,在衍生类中改变访问模式是合法的。

这与非虚拟界面习惯用法在形式上相似,但在意图上不同。 这里给出了一些理由:

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

至于为什么实际上要在基中创建public而在派生中创建private而不创建privateprotected继承,我不明白。

匿名用户

这是法律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()

基本上,您在表达式中引用的声明规定了访问模式-但是虚函数破坏了作为另一个函数,那么命名的那个实际上可能会被调用。

匿名用户

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

现在,它是否做了你想要它做的事情,这是另一个问题。 我相信访问模式不是方法签名的一部分,这意味着调用base的Foo虚拟方法最终确实会调用child的Foo方法。

所以结论是:它是合法的C++,它的工作方式是你所期望的。

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