我有三个类,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 { /* ... */ };
此外,cfg
或foo_circuit
中的foo_conn
指针始终指向{{1}的实例是运行时不变量} foo_config
中的ckt
指针将总是指向foo_conn
的实例。目前正在使用foo_circuit
和断言强制执行此操作。目前有两种不同的dynamic_cast
,但未来可能会有更多。
是否可以安排事项,以便foo
和cfg
类的方法仍可访问ckt
和circuit
指针,并在那里使用泛型类型,但在子类的方法中,那些指针具有适当的子类类型,并且上面的不变量变为编译时强制执行?如果是这样,怎么样?如果没有,你会建议我做什么呢?
我更喜欢能够最小化我必须为每组子类编写的样板数量的答案。如果子类在匿名命名空间中定义并且在任何标头中都不可见,我也更喜欢仍然有效的答案。
答案 0 :(得分:0)
如果用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,以获取编译器帮助检测子类中对这些数据成员的所有直接引用。