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
但我认为这看起来非常糟糕,可以追溯到预标题时间
答案 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文件中,作为配置数据,然后每个其他源文件读取该配置文件。
然后更改配置文件时,不需要重新编译。
所有其他文件读取/解析配置文件。
这是处理此类信息的经典方法。
注意:配置文件不包含枚举,而是包含某些格式化数据。