【问题标题】:C++: overriding public\private inheritanceC++:覆盖公共\私有继承
【发布时间】:2011-08-10 20:42:36
【问题描述】:

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

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);
}

反过来呢?如果继承类型是私有的 - B 可以强制一个特定的函数公开吗?

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

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

【问题讨论】:

    标签: c++ inheritance private public


    【解决方案1】:

    您覆盖的内容不会影响访问。因此,您可以像创建公共继承函数的私有覆盖一样创建私有继承函数的公共覆盖。

    私有继承函数的公共覆盖显然要调用真正的函数,而且应该是内联的,所以编译器会将其优化掉。

    【讨论】:

      【解决方案2】:

      如果 B 使用 public 从 A 继承,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 inclass A`

      如果 A 是纯抽象的呢?有影响吗?

      基类是抽象的还是多态的都没有区别。将适用相同的规则。

      受保护在任何组合中都会有什么不同吗?
      不会
      如前 2 个 Q 中所解释的,如果您正在调用一个通过指向 Base 类的指针的虚函数,那么在编译时编译器只检查 Base 类中该成员函数的访问,因为编译器将其视为对 Base 类成员函数的调用。对函数的实际调用在run time 进行评估,该功能称为Runtime PolymorphismDynamic polymorphism,它独立于作为编译时构造的访问说明符。

      总之,

      覆盖基类的成员不会影响访问

      【讨论】:

      • 虽然我选择了这个作为答案,但我建议阅读其他答案以了解更多细节
      • 所以私有继承很危险?因为你认为一切都不能访问,但是你可以通过基类访问私有虚方法。
      • @Sukhanov:不,这并不危险,因为派生类完全控制它是否可以访问其私有基类。所以“A *a = new B();”当 A 是 B 的私有基类时是不允许的
      • 答案并不完全正确。如果 A 是 B 的基类,那么 A 的私有方法确实无法通过 A* 类型的指针访问,但仍然可以使用 using A::my_func; 语法将其在 B 中公开。如果 A 是 B 的私有基类,这仍然是正确的。=> 覆盖基类的成员确实影响访问,但不会影响基类本身
      【解决方案3】:

      区别

      如果 A 是纯抽象的怎么办?有区别吗?

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

      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
      

      说明

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

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

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

      【讨论】:

      • 请告诉我们实现这种结构是不好的还是not bad 的做法?
      • @mr5 即便如此,它也是一个流程和潜在问题的来源。顺便说一句,Nawaz 非常清楚的解释。
      【解决方案4】:

      ==> If B inherits from A using public, can B override one of the functions and force it to be private?

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

      ==> if the inheritance type is private - can B force a specific function to be public?

      如果继承类型是私有/受保护的,那么您不能将派生类的对象分配给基类指针/引用。例如你不能跟风!!

      A* p = new B; // error
      

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

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

      ==> Would protected make any difference in any combination?

      没有区别(相对于基类)

      【讨论】:

        【解决方案5】:

        我正在浏览其他人的帖子,发现与在 Derived 类中继承为 private/protected 时遇到的错误相关的解释有些令人困惑/不完整。

        考虑下面的代码sn-p,

        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 因此分配 pointer/reference 类型为 @987654329 是非法的@ 指向class A 类型的指针/引用。因此,派生类中私有/受保护的重写虚函数的访问仅在public 中继承时有效。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-11
          • 2011-01-05
          • 1970-01-01
          • 1970-01-01
          • 2017-11-16
          • 2011-05-31
          相关资源
          最近更新 更多