2011-07-06 57 views
0
struct A { 
    B b; 
    A(int x):b(x){} 
    A(int x, float g) // how to implement this? I want to init b as a C. 
}; 
struct B { 
    enum {e_c, e_d} type; 
    int i; 
    B(int i_):i(i_){} 
}; 
struct C : public B { 
    float f; 
    C(int i_, float f_):B(i),f(f_){} 
}; 
struct D : public B { 
    double ff; 
    D(int i_, double d):B(i),ff(d){} 
}; 

也许还有另一种方法来编码?最初我只有B类,但我决定分割它,所以我没有向B添加(不兼容/互斥)字段。我的解决方案是,当A使用b时,它检查b的枚举以查看它是什么类型,然后将B *转换为C *或D *以获得浮点数或双精度值。我的问题是现在我不知道如何让A初始化b。该语言甚至让我做这样的事情?用子类的ctor初始化

编辑:我刚刚意识到A的b不可能已经分配了空间来允许C或D的额外字段。没有任何可用空间来存储浮点数或双精度值。所以我想正确的方式去做我想做的事情就是加入B union {float f; double ff;};

+0

由于您有一个类型为“B”的实际对象成员,因此您不能将init初始化为'C'!你**可以使对象成为'B *',但为什么不直接让'C'类型的成员? –

+0

无论如何,在基类中枚举枚举可能的派生类闻起来就像即将发生的设计车祸。如果您发布实际问题,我们可以考虑更好的解决方案。 –

+0

我想用另一种方式来解释我的问题是:还有更多的OOP方式来做一个工会吗?我只知道如果我使用联合,就像在这个例子中说的那样,它有一个float和一个double,并且我将double值解释为一个float值,我会得到垃圾,这可能会使讨厌的错误。 –

回答

2

你的例子有点困惑。但是,也许你想要一个指针?

struct A { 
    B *b; 
    A(int x):b(new B(x)) {} 
    A(int x, float g):b(new C(x,g)) {} 
    ~A() { delete b; } // Very important! 
}; 

请注意,如果你这样做,B必须有一个虚析构函数。您还需要考虑复制A对象意味着什么。

+0

**必须**提及'B'虚拟析构函数! :-)并且让'A'在您处理时不可复制。另外,OP将enum放入'B'的想法使得它看起来像是即将到来的糟糕的设计选择... –

+0

@Kerrek:啊,好点,没有发现虚拟驱动器从OP的代码中缺失。复制建筑/作业可能很容易导致沿着花园路径的切线,但我也会提到。 –

1

您的编辑是正确的。

可能正常的做法是按照(最好是智能)指针存储B,并在相应的构造函数中分配正确的类型。