需要在泛型和子类代码中相互引用的C ++类

时间:2011-12-02 03:53:02

标签: c++ inheritance

我有三个类,configcircuitconn,它们互相指向,如下所示:

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    { /* ... */ };

此外,cfgfoo_circuit中的foo_conn指针始终指向{{1}的实例是运行时不变量} foo_config中的ckt指针将总是指向foo_conn的实例。目前正在使用foo_circuit和断言强制执行此操作。目前有两种不同的dynamic_cast,但未来可能会有更多。

是否可以安排事项,以便foocfg类的方法仍可访问cktcircuit指针,并在那里使用泛型类型,但在子类的方法中,那些指针具有适当的子类类型,并且上面的不变量变为编译时强制执行?如果是这样,怎么样?如果没有,你会建议我做什么呢?

我更喜欢能够最小化我必须为每组子类编写的样板数量的答案。如果子类在匿名命名空间中定义并且在任何标头中都不可见,我也更喜欢仍然有效的答案。

1 个答案:

答案 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,以获取编译器帮助检测子类中对这些数据成员的所有直接引用。