Getter for private union - c ++

时间:2014-10-02 14:03:25

标签: c++ unions

我有一个带有私人联盟的班级Foo

class Foo
{
  public:
    static Foo foo(int type);
    static Foo foo(double type);
    static Foo foo(bool type);
    static Bar getBar(Foo foo);
  private:
    union Bar
       {
          int iBar;
          double rBar;
          bool bBar;
        } bar;
};

我可以写一个返回相应Bar的通用getter吗?

我试过了:

Bar Foo::getBar(Foo foo) 
  {
    return foo.bar;
  }

和其他变体但编译器没有识别名为" Bar"在" Foo"。

3 个答案:

答案 0 :(得分:2)

两件事 - 与数据和函数成员不同,成员类型需要在使用之前声明,并且您需要在类外定义中完全限定嵌套类型:

class Foo {
    // here, compiler doesn't yet know what Bar is
    union Bar {
        int iBar;
        double rBar;
        bool bBar;
    } bar; // now it does
public:
    static Bar getBar(Foo); // so use it
};

   Foo::Bar Foo::getBar(Foo foo) { return foo.bar; }
// ^^^^^

如果它有任何实际用途,您可能还想Bar public。希望有所帮助。

答案 1 :(得分:0)

使用tuple

示例:

// tuple's get
#include <iostream>
#include <tuple>

int main ()
{
  std::tuple<int,char> mytuple (10,'a');

  std::get<0>(mytuple) = 20;

  std::cout << "mytuple contains: ";
  std::cout << std::get<0>(mytuple) << " and " << std::get<1>(mytuple);
  std::cout << std::endl;

  return 0;
}

请注意,如果您有两个元素,则可以使用std::pair

在更新的问题中,您需要转发声明联合Bar,如下所示:

class Foo {
  union Bar;
 public:
  static Foo foo(int type);
  static Foo foo(double type);
  static Foo foo(bool type);
  static Bar getBar(Foo foo);
 private:
  union Bar {
    int iBar;
    double rBar;
    bool bBar;
  } bar;
};

此外,您所做的事情是不可接受的,因为barFoo的私人成员。


请注意,元组和联合并不完全相同。 “元组是一个包含多个值的数据类型。一个联合可以一次保存一种类型的值。”,正如评论所暗示的那样。这意味着元组的数据可以共存,而联合的数据则不能。


因此,如果您不想使用元组,但坚持使用联合,则需要更改您的类并使联合对世界其他地方可见。现在它是私有的,即使你得到它,使用getter函数,你的类外的世界也看不到联合,因此无法使用它。但是,事情变得有点复杂,所以我不明白为什么不使用元组。


可以找到工会的一个很好的例子here。正如预期的那样,它在C语言中,因为联合会在C语言中比在C ++中更频繁。

答案 2 :(得分:0)

为了扩展G.Samaras的答案,你可以这样做:

typedef std::tuple<type0, type1, type2, type3, type4> MyTuple;
MyTuple myTuple;
type0 a = std::get<0>(myTuple);
type1 b = std::get<1>(myTuple); //...etc.

编辑:愚蠢......事实证明,您也可以这样做:

type0 a = std::get<type0>(myTuple);
type1 a = std::get<type1>(myTuple);

...留下答案的其余部分作为如何不承担事情的一个例子

那么如何将0与type0相关联,依此类推?你这样做(未经测试,但应该工作):

class MyTupleWrapper
{
  private:
     template <typename T> class TypeOffset {};
     template <> class TypeOffset<type0> { enum { value = 0; } };
     template <> class TypeOffset<type1> { enum { value = 1; } };
     template <> class TypeOffset<type2> { enum { value = 2; } };
     template <> class TypeOffset<type3> { enum { value = 3; } };
     template <> class TypeOffset<type4> { enum { value = 4; } };
     // ...etc
  public:
     typedef std::tuple<type0, type1, type2, type3, type4> MyTupleType;
     explicit MyTupleWrapper(const MyTupleType& type) : _type(type) {}
     template <typename T>
     const T& Get() { return std::get< TypeOffset<typename T>::value >(_type); }
  private:
     MyTupleType _type;
}

要打破这个构造而不需要太多的实现,就是这样:

一个。您有两个工具 - std::tuple<Type1, Type2, ...>专用类型和std::get<integer>(tupleObject);来获取特定类型。整数参数取决于您定义元组的初始方式...所以如果您的数字是3,则返回值是该元组内部类型列表中的第三种类型(在我们的例子中,type3

湾元组本身支持正常分配...因此允许MyTupleType t; t = type1();。但你不能调用type1 a = t; - 它必须是type1 a = std::get<1>(t);这是愚蠢的,因为你可以有很多元组类型,你不应该记住你在哪个位置定义了type1 in每个元组类型。

℃。这个包装器做了什么(打算做什么?)是能够说type1 a = t.Get<type1>();使用模板重载将编译时中的每个类型转换为它的偏移量。