我有一个抽象基类,想在派生类中实现一个函数。为什么我必须在派生类中再次声明函数?
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; }
我有一个抽象基类,想在派生类中实现一个函数。为什么我必须在派生类中再次声明函数?
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
也可能是一个抽象类(事实上,如果您不声明foo()
in ,您将得到这样的结果derived
)
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。