请考虑以下代码段:
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”正在更改派生类中虚函数的访问模式。
是的,在衍生类中改变访问模式是合法的。
这与非虚拟界面习惯用法在形式上相似,但在意图上不同。 这里给出了一些理由:
关键在于虚拟函数的存在是为了允许定制; 除非它们也需要从派生的类代码中直接调用,否则没有必要将它们设置为私有的。
至于为什么实际上要在基中创建public
而在派生中创建private
而不创建private
或protected
继承,我不明白。
这是法律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()方法。