C ++:重写publicprivate继承

C++: overriding publicprivate inheritance

如果B使用publicA继承,B是否可以覆盖其中一个函数并强制其私有?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A
{
public:
    virtual double my_func1(int i);
    virtual double my_func2(int i);
}

class B : public A // Notice the public inheritance
{
public:
    virtual double my_func1(int i);
private:
    virtual double my_func2(int i);
}

换个方向怎么样?如果继承类型为private,那么B是否可以强制特定函数为public?

如果A是纯抽象的呢?有什么区别吗?

protected在任何组合中会有什么不同吗?


如果B从使用public继承,B是否可以重写其中一个函数并强制其私有?不

虽然my_func1()priavte访问说明符下声明,但仍然可以通过指向class A的指针调用,实际指向class B的对象。

my_func1()的调用在运行时根据指针指向的对象类型进行计算。在编译时,编译程序将my_func1()调用视为对A::my_func1()的调用,由于A::my_func1()是公开的,因此编译器不会只报告错误。只有在运行时才能计算实际的函数调用B::my_func1()

当然,您不能通过class B的对象直接调用my_func1(),尽管因为B::my_func1()是在私有访问说明符下声明的,并且您不能从类外访问私有声明的成员。

换个方向怎么样?如果继承类型是私有的-B是否可以强制特定函数是公共的?不

如果您通过基class A的指针调用my_func1(),那么在编译时,它的计算结果就是调用A::my_func1(),这是Invalid,因为A::my_func1() is declared private in是类A。`

如果A是纯抽象的呢?有什么区别吗?不如果基类是抽象的,或者只是多态的,那就没有区别了。同样的规则也适用。

受保护会对任何组合产生影响吗?不如前2个q中所述,如果要通过指向基类的指针调用虚函数,那么在编译时,编译器只检查基类中该成员函数的访问,因为编译器将其视为对基类成员函数的调用。对函数的实际调用在run time处进行计算,该功能称为Runtime PolymorphismDynamic polymorphism,它独立于作为编译时构造的访问说明符。

总之,

重写基类成员不影响访问


差异

What if A is pure abstract? does it make a difference?

它的唯一区别在于以下几点,即如何使用它们(或不能使用它们):

1
2
3
4
5
A *pa = new B();
pa->my_func2(10); //calls B::my_func2() even though its private!

B *pb = new B();
pb->my_func2(10); //compilation error - trying to access private function

解释

访问说明符是编译时构造,因此编译器在编译时(显然)根据对象(或指针)的静态类型检测到任何违反访问规则的情况。运行时无法检测到此类冲突。

因此,pa->my_func2()起作用,因为编译器认为pa的静态类型是A*,它定义了一个公共函数my_func2(),所以表达式pa->my_func2()通过了编译器的测试。因此它起作用。

但是pb->my_func2()不起作用,因为pb的静态类型是B*,它有一个私有函数my_func2(),所以代码甚至不能编译!


江户十一〔29〕号

不,指向A的指针/引用始终将my_func2视为公共的。您仍然可以使用A*A&调用此方法。(你在Java中问的是可能的)。

埃多克斯1〔34〕

首先,如果继承类型是私有/受保护的,则不能将派生类的对象分配给基类指针/引用。例如,您不能执行以下操作!!

1
A* p = new B; // error

埃多克斯1〔35〕

没有区别(除非您必须在B中定义方法)

埃多克斯1〔37〕

没有区别(关于基类)


您覆盖的内容不会影响访问。因此,可以创建私有继承函数的公共重写,方法与创建公共继承函数的私有重写完全相同。

私有继承函数的公共重写显然必须调用真正的函数,它应该是内联的,因此编译器将对其进行优化。


我浏览了其他人的文章,发现了与派生类中继承为private/protected时遇到的错误相关的解释,有些混乱/不完整。

考虑下面的代码段,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A
{
public:
    virtual double my_func1(int i);
    virtual double my_func2(int i);
}

class B : private A // Notice private inheritance
{
public:
    virtual double my_func1(int i);
private:
    virtual double my_func2(int i);
}

A* ptr = new B; // this is not legal because B has a private base
ptr->my_func1(); // my_func1() is not accessible
ptr->my_func2(); // my_func2() is also not accessible not because it is private but due
                 // base class A being inherited privately

因此,当我们使用private/protected说明符从class A继承class B时,就意味着外界没有人知道class B是从class A继承的,因此将class B类型的pointer/reference分配给class A类型的指针/引用是非法的。因此,只有在public中继承时,派生类中私有/受保护重写虚拟函数的访问才有效。