标题中的枚举导致过多的重新编译

时间:2015-11-11 17:01:42

标签: c++ c

  

John Lakos将这个问题称为阴险的来源   编译时耦合(图0-3,在他的简介中):

我面临的问题是编译了太多文件,因为单个枚举存在物理依赖。

我有一个包含枚举定义的标题:

// version.h
enum Version {
    v1 = 1,
    v2, v3, v4, v5, ... v100
};

这被数百个文件使用。 每个文件定义一个对象类,必须从磁盘中读取, 使用read()函数。 Version用于确定数据的读取方式。

每次引入新的类或类成员时,都会在枚举

中附加一个新条目
// typeA.cpp
#include "version.h"

void read (FILE *f, ObjectA *p, Version v) 
{
    read_float(f, &p->x);
    read_float(f, &p->y);
    if (v >= v100) { 
        read_float(f, &p->z);  // after v100 ObjectA becomes a 3D
    }
}

// typeB.cpp
#include "version.h"

void read (FILE *f, ObjectB *p, Version v)
{
    read_float (f, &p->mass);
    if (v >= v30) {
        read_float (f, &p->velocity);
    }
    if (v >= v50) {
        read_color (f, &p->color);
    }
}

现在,正如您所看到的,一旦ObjectA发生变化,我们就必须向v100引入一个新条目(比如Version)。因此,即使只有type*.cpp read() ObjectA条真正需要v100条目,也会编译所有type*.cpp个文件。

如何对客户端(即int)代码进行最少的更改来反转对枚举的依赖性,以便只编译必要的.c文件?

这是一个可能的解决方案,我想到了,但我需要一个更好的解决方案:

我想我可以将枚举放在.cpp文件中,并使用相应枚举成员的值公开//version.cpp enum eVersion { ev1 = 1, ev2, ev3, ev4, ev5, ... ev100 }; const int v1 = ev1; const int v2 = ev2; .... const int v100 = ev100; // introduce a new global int for every new entry in the enum

Version

以某种方式为//version.h typedef const int Version; 类型设置别名

// typeA.cpp
#include "version.h"

extern Version v100;    ///// *** will be resolved at link time

void read (FILE *f, ObjectA *p, Version v) 
{
    read_float(f, &p->x);
    read_float(f, &p->y);
    if (v >= v100) { 
        read_float(f, &p->z);  // after v100 ObjectA becomes a 3D
    }
}

并且仅引入每次所需的const int值:

B.pm

但我认为这看起来非常糟糕,可以追溯到预标题时间

2 个答案:

答案 0 :(得分:1)

我不确定您的版本控制系统。你不能将对象定义与阅读分离吗?

// ObjectA.cpp

#include"ObjectA.h"  

// define ObjectA

void ObjectA::setPar ( float xx, float yy, float zz) 
{
    x = v[0];
    y = v[1];
    z = v[2]; 
}

然后

// typeB.cpp

#include"ObjectB.h"  

// define ObjectB

void ObjectB::setPar ( float mm, float vv, color cc) 
{
    mass = mm;
    velocity = vv;
    color = cc; 
}

然后在一个(大)文件中

// readObject.cpp

#include"version.h"
#include"ObjectA.h"
#include"ObjectB.h"

void read (FILE *f, ObjectA *p, Version v) 
{
    float x,y,z;
    read_float(f, x);
    read_float(f, y);
    if (v >= v100) { 
        read_float(f, z);  // after v100 ObjectA becomes a 3D
    } else z=0.0;          // whatever
    p->setPar(x,y,z);
}

void read (FILE *f, ObjectB *p, Version v)
{
    ...
}

答案 1 :(得分:0)

您可以将枚举放在单独的.cfg文件中,作为配置数据,然后每个其他源文件读取该配置文件。

然后更改配置文件时,不需要重新编译。

所有其他文件读取/解析配置文件。

这是处理此类信息的经典方法。

注意:配置文件不包含枚举,而是包含某些格式化数据。