关于c ++:覆盖私有函数

Overriding private functions

我正在处理一个类(称为类D),该类是从一个类(称为类B)派生的,将由另一个类继承(称为类E)。我希望类E的实例能够访问其父类的所有公共函数,但我特别希望防止类E覆盖父类中的任何虚拟函数。

我认为通过重写类D的私有部分中的函数,可以防止派生类重写,但似乎不是这样。它编译并运行E类中的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>

//an abstract base class
class b
{
public:
    virtual ~b() = default;
protected:
    virtual void print() = 0;
    virtual void print_two()
    {
        std::cout <<"base class" << std::endl;
    }
};

class d: public b
{
public:
    virtual ~d() = default;
private:
    void print() override // note this is not virtual -adding final here does the trick
    {
        std::cout <<"class d" << std::endl;
    }
    using b::print_two; //this doesn't work either
};

class e : public d
{
public:
    void print() override //why is this possible given the function it's overriding is private and non-virtual?
    {
        std::cout <<"class e" << std::endl;
    }

    void print_two() override //why is this possible given the function it's overriding is private and non-virtual?
    {
        std::cout <<"print two class e" << std::endl;
    }
};


int main()
{
    e foo;
    foo.print();
    foo.print_two();

}

所以有两个问题:为什么我可以重写一个在祖父母中是虚拟的而不是在父母中是虚拟的函数?为什么我可以重写一个在祖父母中受保护但在父母中是私有的函数?

我在g++和clang中尝试过,它编译时没有错误或警告(wall-wextra-wpedantic)


Why can I override a function that is virtual in a grandparent but not virtual in a parent?

没有这样的事。一旦一个函数被声明为虚函数,它在所有派生类中都是隐式虚函数。接近"非虚拟化"成员函数的唯一方法是声明它final。这将使其无法进一步重写,但当通过祖先引用/指针调用时,它仍将受到动态调度的影响。然而,任何通过孩子的访问(声明为final或其死者)都可以静态解决。

Why can I override a function that is protected in a grandparent but private in a parent?

访问说明符不会影响名称的可见性。它们只影响该名称的使用位置。定义相同的函数将重写父级的实现,并由动态调度调用。再一次,因为这不是属于名称"访问"领域的东西。

如果子级在父级中是私有的,则子级不能引用父级的实现(Parent::foo),也不能引用使用接口的外部代码。它确保只以受控方式调用函数。对于测试前后条件非常有用。