【问题标题】:Does public inheritance allow to override the base classes member accessors?公共继承是否允许覆盖基类成员访问器?
【发布时间】:2015-10-26 13:51:51
【问题描述】:

我在代码示例中读到了一些奇怪的东西。有一个基类和一个派生类。派生类是从具有公共继承的基类派生的。

class baseClass
{
public:
    void foo();
}

class derivedClass : public baseClass
{
protected:
    void foo();
}

派生类还覆盖方法foo() 的访问器。 foo()baseClass 中是public,在derivedClass 中是protected。它可以构建和工作,但我不明白为什么有人会这样做,以及在多大程度上允许这样做。例如,protected 缩小了访问范围,所以它是允许的,但你不能用 public 覆盖基类受保护的方法?我不知道。

【问题讨论】:

  • 它不会覆盖,它会隐藏。
  • 抱歉,我显然使用了错误的术语。你能解释一下区别吗?
  • derivedClass中定义了一个新的foo(),并隐藏了基类的foo(),即不能从派生类中调用。 derivedClass中的新foo()与基类的无关,即与基类成员foo()的访问无关。
  • 只有虚成员函数可以被覆盖。

标签: c++ inheritance public protected


【解决方案1】:

你写的有点棘手。您的代码的结果不会是您所期望的。如果您创建和使用 derivedClass 实例,您就不能调用 foo() 因为它受到保护:

derivedClass object;
object.foo(); // Compilation error. Cannot access.

但是如果你创建一个指向derivedClass类对象的指针并调用foo()函数,它将调用baseClassfoo()而不是derivedClassfoo(),因为它不是一个虚函数在基类中。

baseClass* object = new derivedClass;
object->foo(); // This will call baseClass::foo();

当您隐藏该功能时就是这种情况。如果将virtual 关键字添加到foo(),则将调用derivedClassfoo()

class baseClass
{
public:
    virtual void foo();
}

class derivedClass : public baseClass
{
protected:
    virtual void foo() override;
}

用法:

baseClass* object = new derivedClass;
object->foo(); // This will call derivedClass::foo();

【讨论】:

  • 请注意此处使用 C++11 关键字 override。如果您不小心隐藏而不是覆盖基类函数,它实际上会生成一条错误消息。 (这就是它的引入目的。)
【解决方案2】:

虚拟函数可以被覆盖。这就是虚函数的要点之一。

但是,在您的示例中,derivedClass::foo() 隐藏了baseClass::foo()。它不会覆盖它。

这可以证明如下

//  your class definitions here
int main()
{
     baseClass b;
     derivedClass c;
     baseClass *pb = &b;
     baseClass *pc = &c;

     b.foo();     // will call baseClass::foo()
     pb->foo();   // will also call baseClass::foo()
     pc->foo();   // will also call baseClass::foo()  (not derivedClass::foo() which would be the case if baseClass::foo() was virtual)

     c.foo();     //  will attempt to call derivedClass::foo(), which the compiler will reject since it is protected                      
}

如果derivedClass::foo()public,则语句c.foo() 将编译,并将调用derivedClass::foo()。根据编译器和编译器设置,编译器可能会发出关于 baseClass::foo() 被隐藏的警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    相关资源
    最近更新 更多