重构函数调用,同时减少生成的类定义的代码重复

时间:2009-11-08 19:24:31

标签: c++ refactoring

我有一个包含大约400个函数声明的头文件及其相应的源文件及其定义。

为了在运行时用mock替换实现,我想用对包含实现的对象的调用替换实现(指向实现的指针--pImpl)。

这意味着我将拥有以下文件:

  • mainFile.h - 包含以前的方法声明(必须保留,因为我不能用客户端代码替换接口)
  • IImpl.h - 实现对象的抽象基础(接口)
  • mainFile.cpp - 将包含方法定义,所有它都在IImpl *上调用相应的方法
  • SpecificImpl.cpp - 包含特定实现的声明和定义
  • MockImpl.cpp - 包含测试期间使用的实现的声明和定义

这个问题的主要问题是400个方法声明的重复,它们出现在主头文件中,并且再次出现在每个类定义中。

有什么方法可以避免这种重复吗?我正在尝试使用宏,但随后包含的顺序变得过于具体......

5 个答案:

答案 0 :(得分:3)

这样的事情:

//=======================================
// Macro definition of method list
//=======================================
#define METHOD_LIST(ABSTRACT) \
    virtual void Foo1() ABSTRACT; \
    virtual void Foo2() ABSTRACT; \
    virtual void Foo3() ABSTRACT

//=======================================
// Declaration of Abstract base class
//=======================================
class IBase
{
public:
    METHOD_LIST( = 0);
};

//=======================================
// Declaration of Specific
//=======================================
class CSpecific : public IBase
{
public:
    METHOD_LIST();
};

//=======================================
// Declaration of Mock class
//=======================================
class CMock : public IBase
{
public:
    METHOD_LIST();
};

更新...

如果你想让它变得更加宏观,你可以将宏改为:

#define METHOD_LIST(VIRTUAL, ABSTRACT) \
    VIRTUAL void Foo1() ABSTRACT; \
    VIRTUAL void Foo2() ABSTRACT;

这将允许您声明不属于任何对象的常规函数​​列表:

对于抽象类:

METHOD_LIST(virtual, =0)

对于派生类:

METHOD_LIST(virtual, ;)

对于常规功能列表:

METHOD_LIST(;, ;)

如果您需要调试这个混乱,那么我建议使用'g ++ -M'来查看预处理器的结果。

答案 1 :(得分:1)

使用纯虚拟类作为接口和具有重构支持的良好IDE。

纯虚拟类就像API契约(在其他语言中有时称为接口)。您声明一个方法一次,然后在3-4个其他类中继承它。你只更改了接口中的一个方法,它在依赖类中被改变了......或者至少那些不再编译的方法,你知道你也必须在那里进行更改。

详细了解此信息,例如在wikipedia

答案 2 :(得分:0)

一种方法是使用重构工具;大多数现代IDE都有。例如,Eclipse CDT有一个重构选项。格德也提出了一个。

另一种方法是使用代码检测工具,如pin。这些工具主要用于分析,但可能适合您的目的。

<强>更新

如果您的问题不仅仅是编写代码,而是维护更多,我认为pin是一个不错的选择(运行时更改)。另一种方法是使用面向方面的编程。例如,Aspect C++

答案 3 :(得分:0)

编写一个代码生成器,它从主头文件中获取方法声明,并将它们复制到SpecificImpl和MockImpl头文件中。

答案 4 :(得分:0)

如果这是一个常见问题,那么学会使用模板,并研究通用/生成/元编程技术。 (兔子洞很深)