1

我想做的是创建一个新的自定义数据类型,它的行为与所有其他原始类型一样。具体来说,这种数据类型看起来像一个定点分数。我创建了一个类来表示这种数据类型,称为“class FixedPoint”,其中有一些方法可以将“FixedPoint”类型转换为“int”或“double”或“unsigned int”等。这很好。

现在,如果我想从中转换"int" to "FixedPoint"怎么办?最初我的解决方案是有一个构造函数:

FixedPoint(int i) { /* some conversion from 'int' to 'FixedPoint' in here */ }

这行得通......但你不能像这样把它放到一个联合中:

 union {
   FixedPoint p;
 };

这会中断,因为“FixedPoint”没有隐式的普通构造函数(我们刚刚定义了一个构造函数,“FixedPoint(int i)”)。

总而言之,整个问题是“我们想要cast from some type T to type FixedPoint without explicitly defining a constructor在联合中使用我们的 FixedPoint 类型”。

我认为解决方案是但无法在线找到任何证据:定义一个重载的全局类型转换运算符以从“int”转换为“FixedPoint”。

有没有办法在不使用类构造函数的情况下做到这一点?我希望能够在联合中使用这个类。我尝试过的(在全球范围内):

operator (FixedPoint f, int a) { ... } //compiler complains about this is not a method or non-static.

还有一个小例子表明联合不喜欢构造函数(他们喜欢 POD)

class bob
{
  public:
    bob(int a) { m_num = a; }
  private:
    int m_num;
};
void duck()
{
  union 
  {
    bob a;
  };
}

在 Visual Studio 中看到的这个错误是:

error C2620: member 'duck::<unnamed-tag>::a' of union 'duck::<unnamed-tag>' has user-defined constructor or non-trivial default constructor

有任何想法吗?谢谢

4

3 回答 3

0

我很难看到你会尝试使用它来做什么。必须不断确保sizeof(FixedPoint) == sizeof(int)并且假设还有其他隐藏的陷阱,例如字节序,这似乎很臭。也许我应该在这里稍微备份一下,联合只会将一个值从一种类型“转换”为另一种类型,因为它需要一块内存并将其作为不同的类型引用。IE

union BadConverter
{
    int integer;
    double fraction;
};

BadConverter.fraction = 100.0/33.0;
BadConverter.integer = ?;

我很确定整数不会是 3,它会变成整数字节与其共享的双精度内存块。

工会似乎不太适合这种事情。我想只是从所有原始类型中定义一堆赋值运算符。IE

class FixedPoint
{
    FixedPoint& operator=(int value);
    FixedPoint& operator=(double value);
    ..etc..
    //Maybe something like this?
    template<typename T>
    FixedPoint& operator=(const T& value)
    {
        value = boost::lexical_cast<int>(value);
        return *this;
    }
}
于 2010-09-28T21:36:00.573 回答
0

自定义转换运算符必须是要从转换的类的成员。不需要非平凡的构造函数。

编辑:我修改了示例以利用 aunion因为这是您要问的。

EDIT2:如果您尝试另一种方式(构造)并且不想要构造函数,请参见下文。

#include <string>
#include <sstream>
using namespace std;

class FixedPoint
{
public:
    operator std::string() const
    {
        stringstream ss;
        ss << x_ << ", " << y_;
        return ss.str();
    }
    int x_, y_;
};

union Items
{
    FixedPoint point_;
    int val_;
};

int main()
{
    Items i;
    i.point_.x_ = 42;
    i.point_.y_ = 84;
    string s = i.point_;
}

如果您尝试采用另一种方式——例如,在我的示例中从inttoFixedPoint开始——那么通常的方法确实是使用转换构造函数。鉴于您不想要一个重要的构造函数,您必须求助于转换函数。

FixedPoint make_fixed_point(int x, int y)
{
    FixedPoint ret;
    ret.x_ = x;
    ret.y_ = y;
    return ret;
}

union Items
{
    FixedPoint point_;
    int val_;
};


int main()
{
    Items i;
    i.point_ = make_fixed_point(111,222);
}
于 2010-09-28T20:57:28.437 回答
-2

你不能只添加一个默认构造函数,让它成为联合的一部分。

例如:

class bob
{
  public:
    bob(int a=0) { m_num = a; }
  private:
    int m_num;
};
void duck()
{
  union 
  {
    bob a;
  };
}

通过给出a=0默认值,它应该能够被放入一个联合中。不过我自己没试过。

于 2010-09-28T21:07:24.983 回答