C ++:自定义数据类型 - 类型转换和联合问题

时间:2010-09-28 20:47:17

标签: c++ types overloading operator-keyword

我要做的是创建一个新的自定义数据类型,其行为与所有其他基本类型相同。具体而言,此数据类型显示为固定点分数。 我已经创建了一个类来表示这种数据类型,称为“类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

有什么想法吗? 感谢

3 个答案:

答案 0 :(得分:0)

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

编辑:我重复了这个例子以使用union,因为这是你所要求的。

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_;
}

如果你试图走另一条路 - 例如,从我的例子中的intFixedPoint - 那么通常的方法就是使用转换构造函数。鉴于您不需要非平凡的构造函数,您必须求助于转换函数。

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);
}

答案 1 :(得分:0)

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

union BadConverter
{
    int integer;
    double fraction;
};

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

我很确定整数不会是3,无论double的内存块是什么,整数字节都与它共享。

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

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;
    }
}

答案 2 :(得分:-2)

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

例如:

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

通过赋予a=0默认值,它应该能够被放入联合中。不过我自己也没试过。