考虑一下:
struct Base {
virtual void fn() = 0;
};
struct A: Base {
virtual void fn();
};
struct B: A {
// fn is not overridden here
};
基本上,fn
在A
中实施。 B
来自A
,而B
并非覆盖fn
。
我希望有技巧让B
必须覆盖fn
,因为如果没有覆盖它就是错误。
可以这样做吗?编译时错误(或警告)是最好的,但如果不可能,那么运行时错误也是可以的。我想知道,如果有人忘记在派生类中覆盖fn
。
原因是什么? fn
可以返回与课程相关的信息。例如,它可以返回类名。或者它可以返回对象使用的已分配空间量(用于调试目的)。或者做一些与课程相关的任务(例如,加载/保存其状态)。
答案 0 :(得分:2)
如果fn
未覆盖B
,则无法强制编译器生成错误。
您可以稍微修改一下代码以获得所需内容。
让A::fn
成为纯虚拟的。将实现保留为A
中的实现。请记住,即使它被声明为纯虚拟,也可以实现A::fn
。
这会强制您覆盖fn
中的B
。 B::fn
的实施可以根据需要使用尽可能多的A::fn
。
truct Base {
virtual void fn() = 0;
};
struct A : Base {
virtual void fn() = 0;
};
void A::fn()
{
// Add implmentation details
}
struct B : A {
// fn must be overridden here
virtual void fn();
};
void B::fn()
{
A::fn();
// Add additonal logic for B
}
如果A::fn
被称为on B
对象,则可能会生成运行时错误。
这是一种方法。
#include <iostream>
struct Base
{
virtual void fn() = 0;
virtual int getTypeID() = 0;
protected:
static int getNextID()
{
static int nextid = 0;
return ++nextid;
}
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
struct A : Base
{
virtual void fn();
virtual int getTypeID()
{
return getClassTypeID();
}
private:
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
void A::fn()
{
if ( this->getTypeID() != A::getClassTypeID() )
{
// Problem.
std::cout << "ERROR. fn() called on a derived class object.\n";
}
else
{
std::cout << "OK. fn() called on an A object.\n";
}
}
struct B : A
{
virtual int getTypeID()
{
return getClassTypeID();
}
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
int main()
{
A* a1Ptr = new A;
A* a2Ptr = new B;
a1Ptr->fn();
a2Ptr->fn();
}
输出:
OK. fn() called on an A object.
ERROR. fn() called on a derived class object.