派生抽象类中的纯虚方法

时间:2013-03-24 20:25:09

标签: c++ inheritance virtual

说我们有这个:

class A
{
   public:
   virtual void foo() = 0;
};

class B: public A
{
   public:
   virtual void foo() = 0;
};

编译器不会抛出任何错误,我猜它是因为B也是一个抽象类,因此它不必从A实现foo。 但这样的构造意味着什么?

1)B中的foo是否隐藏foo来自A?

2)继承自B并且不是抽象类的第一个类,它必须提供两个实现,如:

class C: public B
{
   public:
   virtual void A::foo() {};
   virtual void B::foo() {};
};

编译器只会抱怨B::foo()的实现缺失,但不会抱怨缺少A::foo()

总而言之:这是一种隐藏纯虚方法的方法吗?

3 个答案:

答案 0 :(得分:9)

当你第一次宣布:

class A
{
   public:
   virtual void foo() = 0;
};

您声明方法foo是公共的,虚拟的和纯粹的。当一个类至少包含一个纯方法时,它被称为 abstract 。这是什么意思?这意味着该类无法实例化,因为它需要纯方法实现。

你显然可以从一个抽象类继承(我会说你被迫这样做,否则你需要一个你没有使用的抽象类,除了提供一个继承的接口?)和你也可以从一个抽象类继承而不是实现父类的部分或全部纯方法;在这种情况下,子类也是抽象的,就像你的B类一样:

class B: public A
{
   public:
   virtual void foo() = 0;
};

在B中,您可以轻松省略virtual void foo() = 0;声明,因为该定义已从基类继承。在这种情况下,类B是一个抽象类,因此无法实例化,就像A。

更直接地回答您的问题:

  

来自B的foo是否隐藏foo来自A?

不,它没有。它们都声明了一个纯方法(事实上它是相同的方法),因此没有什么可以真正隐藏

  

第一个继承自B并且不是抽象类的类,是否必须提供两个类似提供的实现?

不,当然不是。如上所述,它们是相同的方法,因此如果C类必须为foo提供实现,它应该只实现foo

class C: public B
{
   public:
   virtual void foo() {};
};

答案 1 :(得分:7)

  

0)编译器不会抛出错误...

当您尝试从AB实例化一个对象时,它会引发错误。不是在你继承和宣布它们的时候。

  

1)B的foo是否隐藏了A?

没有。它超越A::foo而不是隐藏它。

  

2)继承自B并且不是抽象类的第一个类,   是否必须提供两种实现方式......

没有。只需覆盖foo并为其创建一个实现。

class C : public B
{
public:
    virtual void foo()
    {
        std::cout << "ABCD" << std::endl;
    }
};


int main()
{
    C c;
    A *a = &c;
    a->foo(); //  Prints ABCD string and proofs B::foo doesn't hide A::foo
}

答案 2 :(得分:1)

我用gcc 4.5.3编译了你的代码,它给出了以下错误信息:

error: cannot define member function ‘A::foo’ within ‘C’
error: cannot define member function 'B::foo' within 'C'

在您的示例中,类AB都是抽象类,因为foo是纯虚拟的。它们只定义B的派生类应该实现foo的行为,因为没有默认行为要使用(如果派生类不再是抽象的)。

Question 1:Does foo from B hide foo from A?

由于fooB中的A具有完全相同的名称,因此相同的签名和foo在基类中是虚拟的,因此它不会隐藏,它会覆盖。仅供参考:如果签名相同并且在基类中声明为虚拟,则派生类的函数overrides是基类函数。如果你打电话 通过指针或对基类的引用,在函数中 派生类被调用。它“覆盖”基类中的那个。 Hiding只有在通过a调用非虚函数时才会发挥作用 指针或引用或直接与派生类的对象。一个 派生类'函数隐藏所有具有相同名称的基类函数。

Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations

没有。您可以执行以下操作:

  class C: public B
  {
   public:
      virtual void foo()
      {
        cout << "foo defined in c" <<endl;
      }
 };