【问题标题】:How to add union members in an inherited class/struct如何在继承的类/结构中添加联合成员
【发布时间】:2019-02-15 18:56:21
【问题描述】:
struct Foo 
{
    union {
        struct { int a, b; };
        int index[2];
    };
};

struct Bar : public Foo 
{
    union {
        // Foo members
        struct { int barA, barB; };
    };

};

int main()
{
    Foo f;
    Bar b;
    // I want it so that
    &b.a == &b.barA;
    // in the same way that
    &f.a == &f.index[0];
}

有什么办法可以让 Bar 的成员与其父类“联合化”?

非常感谢,非常感谢任何帮助

编辑: 这是所要求的用例:

struct Vec2
{
    union {
        float index[2]; 
        struct { float x, y; };
    };

    Vec2(float xVal, float yVal)
        : x(xVal), y(yVal)
    {   
    }

    ~Vec2() {}

    Vec2 & add(const Vec2 & b) { /* implimentation */ }
    Vec2 & sub(const Vec2 & b) { /* implimentation */ }

};

struct ComplexNumber : public Vec2
{
    union {
        // Vec2 members
        struct { float real, imag; };
    };

    ComplexNumber(float realPart, float imagPart)
        : real(realPart), imag(imagPart)
    {
    }

    ComplexNumber & mul(const ComplexNumber & b) { /* implimentation */ }
    ComplexNumber & div(const ComplexNumber & b) { /* implimentation */ }
};

int main()
{
    ComplexNumber a(5, 2);
    ComplexNumber b(7, 8);
}

我希望不仅能够解决 a 和 b 的 Vec2 成员, 但也可以使用 Vec2 中声明的函数,甚至可能添加 ComplexNumbers 和 Vec2s 可以互换。

【问题讨论】:

  • Bar 是否必须从 Foo 继承 (is-a),还是可以包含 (has-a) Foo?
  • struct { int a, b; }; 是一个匿名结构成员。 C++ 中不允许使用匿名结构。
  • 这是一个巧妙的问题。我可以看到为什么它应该被禁止的很多原因,派生类不能改变基类的大小,但是如果大小没有改变,是否有足够的用例来注入允许的异常是否纳入标准?
  • 建议:Gabe,如果这不仅仅是出于学术目的,请将您的用例添加到问题中。有人可能会给你一个解决方法或替代方案。
  • 以什么方式禁止“struct {int a, b;}”?我正在使用 g++ 编译并启用所有警告,但没有得到任何警告。

标签: c++ oop inheritance struct unions


【解决方案1】:

您在FooBar 中的工会是匿名工会。这是一种语法糖,它允许访问它们的成员,就好像它们在封闭类中一样:

[class.union.anon]/1:

出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为是在声明匿名联合的范围内定义的。

但这只是方便会员访问。匿名联合对象未合并到其封闭类中。因此,在Bar 中有两个不同的联合(对象位于不同的地址)。这些不能合并/合并。

顺便说一句,标准明确禁止 union 以任何方式继承:

[class.union]/3:

联合不应有基类。联合不应用作基类。

没有办法做你想做的事。

查看您的具体情况,您希望在派生类中建立的合并联合似乎与基类的各个部分具有一对一的关系。鉴于这些情况,作为一种解决方法,您可以使用一些引用来引用同一成员:

struct ComplexNumber : public Vec2
{
    float &real=x, &imag=y;

    ComplexNumber(float realPart, float imagPart) : Vec2 (realPart, imagPart)
    {
    }
    ...
 }; 

当然,您需要实现规则 3,以避免任何问题(例如,引用指向错误的对象,以防复制构造函数或赋值完成)。

现在真正的问题是复合体是否是 Vec2。就个人而言,我宁愿采用更清晰的方法,使复杂的成为独立的类并拥有一个 Vec2 成员。在这种情况下,复合体将重新定义 Vec2 操作并将成员函数转发给 Vec2 成员。

【讨论】:

  • 清晰的解释和更好的推荐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多