如何删除从基类继承的纯虚函数?

5
假设我有一个名为Human的基类,BabyAdultHuman的子类。Human有一个名为run的纯虚函数,我不想让Baby继承run,但如果我不覆盖runBaby将变成一个抽象类。
class Human{
 public:
   // Some human attributes.
   virtual void run()=0;
};

class Adult: public Human{
 public:
   void run(){
      // Adult running function
   }
};

class Baby: public Human{
 public:
   void run()=delete; //error

   // If I don't override `run` then Baby is marked as an abstract class

   void crawl(){
     // Baby crawling function.
   }
};

如果我使用=delete标记run,会导致错误。
prog.cpp:19:10: error: deleted function ‘virtual void Baby::run()’
     void run()=delete;
          ^~~
prog.cpp:6:22: error: overriding non-deleted function ‘virtual void Human::run()’
         virtual void run()=0;
                      ^~~

可能不是很好的例子,但我想要的是在Baby中继承除了run之外的所有内容。这是否可能?

@ThePhilomath,我无法理解如何使析构函数成为纯虚函数就可以解决在Baby中禁止使用run的问题。我是c++的新手,请详细解释并将其作为答案发布? - Ch3steR
8
如果并非所有人都能奔跑,那么也许这不应该在他们的界面中。在这里应牢记LSP(最少惊喜原则)。 - StoryTeller - Unslander Monica
由于答案中的示例,所以不可能。你可以将其保留为空 void run(){},在其中 throw 一个错误,或者触发一个 assert。因为这是动态多态性,所以在编译时无法做任何事情。 - JHBonarius
@StoryTeller-UnslanderMonica 是的,LSP原则很有道理。对于那些想了解LSP的人,请参考LSP - Ch3steR
@Peter 谢谢你的建议。实际上,我并不打算通过这个来解决任何问题,只是出于好奇。我正在学习=delete,想知道是否可以抑制一个纯虚函数。 - Ch3steR
显示剩余4条评论
1个回答

10

这是不可能的。考虑以下代码:

Human *CreateAPerson() {
  return new Baby();
}

int main() {
  Human *human = CreateAPerson();
  human->run();
}
编译器无法知道human->run()是非法的。

有没有办法在 Baby 中禁止 run - Ch3steR
@Ch3steR 是和不是。不能使用动态继承、纯基类和类型擦除。你可以将其设置为私有,但它仍然会存在。它将能够像婴儿一样运行,但也能像人类一样运行。使用CRTP/mixins可能会实现这种情况,并在派生类中“禁用”其中一个或另一个方法,但这将是一个复杂的解决方案,在这种情况下必须有某种默认的空(返回错误状态?)方法。 - Swift - Friday Pie
@Ch3steR 添加类似于assert(false)的内容。但我猜你应该创建另一个接口,声明虚拟的run(Runnable?),并且不要从中继承Baby - fas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接