【问题标题】:Is it possible to convert virtual non-static to static method without doing major refactoring?是否可以在不进行重大重构的情况下将虚拟非静态方法转换为静态方法?
【发布时间】:2023-01-05 01:19:03
【问题描述】:

考虑以下:

class RecordCommon {
public:
   virtual const char* GetShortName(void) const = 0;
   ...
   virtual void DoSomeWork(void);
};

class RecordCLDT : public RecordCommon {
   virtual const char* GetShortName(void) const { return "CLDT"; }
};

void RecordCommon::DoSomeWork(void) {
   ...
   log(GetShortName());
   ...
}

我想要的是像 RecordCLDT::GetShortName(void) 这样的静态方法,它会在不对项目进行重大重构的情况下返回“CLDT”。也许这可以通过一些宏或智能模板技术来完成?

我需要让 RecordCommon::DoSomeWork(void) 调用正确的 GetShortName() 函数,如果我只是将虚拟 GetShortName() 替换为静态函数则不会。

重写 RecordCommon 的每个子类将非常耗时,尤其是因为代码中使用了虚拟 GetShortName()。

【问题讨论】:

  • 这就是 shell/perl/python 脚本的用途。不幸的是,在 C++ 的某个地方没有神奇的按钮,只需要找到并按下它就可以完成所有事情。有时您必须自己完成所有工作。备选方案:第 1 步:启用编译器标志,要求所有覆盖显式标记为 override,否则编译失败。第 2 步:修复所有编译失败。第 3 步:用静态函数替换非静态函数。第 4 步:修复所有编译失败。
  • 为什么你想做一个静态的RecordCLDT::GetShortName吗?你使用this,来区分调用了哪个实现。
  • 我需要让RecordCommon::DoSomeWork(void)调用正确的GetShortName()函数“ 称它为什么?没有给静态函数一个对象来处理,它是决定“正确函数”甚至是什么的对象。

标签: c++ c++17


【解决方案1】:

不,你不应该想要。不管怎样,你自己做的任何事情最终都会表现得像virtual

仅仅因为您没有访问 RecordCLDT 的任何数据成员,并不意味着您可以将其设为静态,您仍然需要它是基类成员的 override 才能调用正确的东西。

【讨论】:

    【解决方案2】:

    virtual 函数起作用是因为对象中隐藏了信息,告诉系统指针/引用是什么对象真的指着。这就是允许为给定对象调用正确函数的原因。

    如果你想删除virtual函数,你必须代替这个功能。也就是说,不是在对象中有隐式数据来说明它是哪种对象,你必须有明确的对象中的数据,不同的函数将查看这些数据以判断它到底是什么。

    这不是一件微不足道的事情,如何做到最好取决于多种因素。您不能只创建一个static 成员,撕掉一些virtuals,并期望一切仍然有效。说明对象类型的数据仍然必须存在,并且必须可以从基类访问。如果删除隐式数据,则必须添加显式数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2011-12-11
      • 1970-01-01
      相关资源
      最近更新 更多