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

John Lakos refers to this problem as an insidious source of
compile-time coupling
(Figure 0-3, in his Introduction):

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

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

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

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

每次引入新的类或类成员时,都会在枚举中附加一个新条目

// 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).因此,所有类型* .cpp文件都将被编译,即使只有ObjectA的read()确实需要v100条目.

如何在对客户端(即类型* .cpp)代码进行最小更改的情况下反转对枚举的依赖性,以便只编译必要的.c文件?

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

我想我可以将枚举放在.cpp文件中,并使用各个枚举成员的值公开int:

//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.h
typedef const int Version;

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

// 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
    }
}

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

最佳答案 我不确定你的版本控制系统.你不能将对象定义与阅读分离吗?

// 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)
{
    ...
}
点赞