我要做的是创建一个新的自定义数据类型,其行为与所有其他基本类型相同。具体而言,此数据类型显示为固定点分数。 我已经创建了一个类来表示这种数据类型,称为“类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
有什么想法吗? 感谢
答案 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_;
}
如果你试图走另一条路 - 例如,从我的例子中的int
到FixedPoint
- 那么通常的方法就是使用转换构造函数。鉴于您不需要非平凡的构造函数,您必须求助于转换函数。
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
默认值,它应该能够被放入联合中。不过我自己也没试过。