为什么需要重新声明接口

Why does an interface needs to be redeclared?

本文关键字:声明 接口 新声明 为什么      更新时间:2023-10-16

我有一个抽象的基类,想在派生类中实现一个函数。为什么我必须再次在派生类中声明函数?

class base {
public:
    virtual int foo(int) const = 0;
};
class derived : public base {
public:
    int foo(int) const; // Why is this required?
};
int derived::foo(int val) const { return 2*val; }

考虑到派生类定义可能位于标头中,而其实现可能位于源文件中。 标头通常包含在多个位置("翻译单元")中,每个位置都将独立编译。 如果您没有声明重写,那么编译器就不会知道任何其他翻译单元中的内容。

在基类中使函数纯virtual的目的是派生类必须重写它并提供自己的实现。
请注意,类中存在纯虚函数会使该类成为抽象类。简单来说,该类充当创建更具体类的接口。不能创建抽象类的对象。

如果不重写派生类中的纯虚函数,

则派生类仅包含继承的基类纯虚函数,并且它本身也充当抽象类。一旦派生类是抽象的,就无法实例化它。
因此,为了实例化派生类,它需要覆盖并因此声明纯虚函数。

你可能认为编译器可以推断出你必须提供derived::foo()的实现,derived但这也可能是一个抽象类(事实上,如果你不用derived声明foo(),这就是你会得到的)

It is to override the abstraction of the base class .

如果不重新声明它,则派生类也是一个抽象类。如果你这样做,那么你现在有一个非抽象的基类型。

因为层次结构可以有更多的层。

struct Base {
    virtual void foo() const = 0;
    virtual void bar() const = 0;
};
struct SuperBase: Base {
     virtual void bar() const override;
};
struct Concrete: SuperBase {
     virtual void foo() const override;
};

在这里,SuperBase没有提供foo的实现,这需要以某种方式指出。

虽然你不能用纯虚函数实例化一个类,但你仍然可以创建一个这样的类:

class base {
public:
    virtual int foo(int) const = 0;
};
class derived : public base {
public:
};
class very_derived : public derived {
public:
    virtual int foo(int) const { return 2; }
};

派生类仍然是一个抽象类,它不能被实例化,因为它不会覆盖foo。在实例化类之前,您需要声明 foo 的非纯虚拟版本,即使您没有立即定义 foo。