我有三个类,config
, circuit
和conn
,它们相互保存指针,如下所示:
struct config { /* ... */ };
struct circuit {
config *cfg;
/* ... */
};
struct conn {
config *cfg;
circuit *ckt;
/* ... */
}
(没有访问控制和指针智能,因为这个程序已经完成了从C到c++的转换。那现在不重要
当这些类被子类化时,它们三个总是在一个组中被子类化:
struct foo_config : config { /* ... */ };
struct foo_circuit : circuit { /* ... */ };
struct foo_conn : conn { /* ... */ };
此外,foo_circuit
或foo_conn
中的cfg
指针将始终指向foo_config
的实例,foo_conn
中的ckt
指针将始终指向foo_circuit
的实例,这是一个运行时不变量。这是目前dynamic_cast
和断言强制执行的。目前有两个不同的foo
s,但将来可能会有更多。
是否有可能安排事项,使cfg
和ckt
指针仍然可以访问泛型circuit
和conn
类的方法,并具有泛型类型,但在子类的方法中,这些指针具有适当的子类类型,并且上述不变式成为编译时强制执行?如果有,怎么做?如果没有,你建议我做什么呢?
我更喜欢那些我必须为每组子类编写的样板文件数量最少的答案。如果子类定义在匿名命名空间中并且在任何头文件中不可见,我也更喜欢仍然有效的答案。
如果你用getter和setter替换所有对数据成员的直接访问,那么你就可以为每个子类定义特定类型的getter和setter,并且编译器可以使用这些来强制类型。下面是一个例子,注意我已经定义了一个模板类来简化子类的创建。
struct config { /* ... */ };
struct circuit {
private:
config *cfg;
protected:
void set_cfg(config* _cfg) { cfg = _cfg; }
config* get_cfg() { return cfg; }
};
template <typename CFG>
struct my_circuit : circuit {
public:
// type specific setters/getters
void set_cfg(CFG* _cfg) { circuit::set_cfg(_cfg); }
CFG* get_cfg() { return dynamic_cast<CFG*>(circuit::get_cfg()); }
};
// below is how you define two different sets of subclasses:
struct foo_config : config { /* ... */ };
typedef my_circuit<foo_config> foo_circuit;
struct bar_config : config { /* ... */ };
typedef my_circuit<bar_config> bar_circuit;
// example usage
foo_config foo_cfg;
foo_circuit foo_ckt;
bar_config bar_cfg;
foo_ckt.set_cfg(&foo_cfg); // okay
foo_ckt.set_cfg(&bar_cfg); // not okay, compiler error!
在基类内部你不需要改变任何东西。在子类内部,您必须用相应的getter替换对这些成员变量的直接访问,以便获得适当的类型转换。注意,我将基类中的数据成员转换为private,以便编译器帮助检测子类中对这些数据成员的所有直接引用。