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