C++ 派生抽象类中的纯虚方法

C++ 派生抽象类中的纯虚方法,c++,inheritance,virtual,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是否隐藏A中的foo 2) 第一个类继承自B,不是抽象类,它是否必须提供以下两种实现: class C: public B {

假设我们有:

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

class B: public A
{
   public:
   virtual void foo() = 0;
};
编译器不会抛出错误,我猜是因为B也是一个抽象类,因此它不必从A实现
foo
。 但是,这样的构造意味着什么呢

1) B中的
foo
是否隐藏A中的
foo

2) 第一个类继承自B,不是抽象类,它是否必须提供以下两种实现:

class C: public B
{
   public:
   virtual void A::foo() {};
   virtual void B::foo() {};
};
编译器仅在
B::foo()
的实现缺失时才会抱怨,但不会抱怨缺失的
a::foo()

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

0)编译器不会抛出错误

当您尝试从
A
B
实例化对象时,它将抛出一个错误,因为它们是抽象的。当您继承并声明它们时就不会了

1) B的foo隐藏了A的foo吗

不。它覆盖了
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
}

C类:公共B类
{
公众:
虚拟void foo()
{

std::cout我用gcc 4.5.3编译了您的代码,它给出了以下错误消息:

error: cannot define member function ‘A::foo’ within ‘C’
error: cannot define member function 'B::foo' within 'C'
在您的示例中,类
A
B
都是抽象类,因为foo是纯虚拟的。它们只定义B的派生类应该实现
foo
的行为,因为没有可使用的默认行为(如果派生类不再是抽象的)

问题1:B中的foo是否隐藏A中的foo?

由于
B
A
中的
foo
具有完全相同的名称、相同的签名,并且foo在基类中是虚拟的,因此它不是隐藏的,而是重写的。仅供参考:如果签名相同并且在基类中声明为虚拟的,则派生类的函数
重写
基类函数。如果调用它
通过对基类的指针或引用
派生类被调用。它“重写”基类中的派生类。
隐藏
仅在通过 指针、引用或直接与派生类的对象关联。A “派生类”函数隐藏具有相同名称的所有基类函数

问题2:从B继承的第一个类不是抽象类,它必须提供两个实现吗

不可以。您可以执行以下操作:

  class C: public B
  {
   public:
      virtual void foo()
      {
        cout << "foo defined in c" <<endl;
      }
 };
C类:公共B类
{
公众:
虚拟void foo()
{

当您第一次申报时:

class A
{
   public:
   virtual void foo() = 0;
};
您正在声明方法
foo
public、virtual和pure。当一个类至少包含一个pure方法时,它被称为abstract。这意味着什么?这意味着该类无法实例化,因为它需要pure方法实现

很明显,您可以从抽象类继承(我想说,您是被迫这样做的,否则您不使用的抽象类需要什么,除了提供从中继承的接口之外?)您也可以从抽象类继承,而不实现父类的部分或全部纯方法;在这种情况下,子类也是抽象的,这是类B的情况:

class B: public A
{
   public:
   virtual void foo() = 0;
};
在B中,您可以很容易地省略
虚拟void foo()=0;
声明,因为定义已经从基类继承。在这种情况下,类B是一个抽象类,因此无法像A一样实例化

要更直接地回答您的问题:

B中的
foo
是否隐藏A中的
foo

不,它不是。它们都声明了一个纯方法(实际上是同一个方法),因此没有什么需要隐藏的

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

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

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

你到底是如何隐藏它的?如果我没有在C中为A::foo()提供实现,我也可以实例化C的一个对象。因此,即使缺少A::foo(),C也可以一直被实例化。因此我认为不知何故,C中不需要A::foo(),因此“隐藏”。因为B继承了A..如果B::foo()不隐藏A::foo()那么为什么不允许C实现它呢?如果你想从
C
中获取一个对象,那么它必须实现
foo
否,
B::foo
A::foo
不同,并且隐藏它(以及覆盖它)我确认GCC确实会抛出错误消息,而Visual C++编译器则不这样。@ Juergen感谢确认。在C类中确实需要代码>虚<代码>。它不能只是<代码>空余(){{},< /C> >?根据C++标准,不需要它。我发现它更可读。