作为Ruby(1.8)的一个例子
i = 4
i.class => fixnum
i += 1.3
i.class => float
这可以用C ++实现吗?
例如
template<class T>
struct Number {};
Number<int> foo;
foo.changeTypeToFloat(); // <-- Possible?
// foo now Float?
答案 0 :(得分:5)
C ++是一种静态类型的语言。变量具有固定类型。您在语言级别可以做的最好的事情是转换为新变量,例如:
int i = 5;
float f = static_cast<float>(i);
或者,您可以编写变体类,并在内部处理转换。但对于上述情况,这确实是语法糖。
答案 1 :(得分:3)
像其他人说的那样,在C ++中,这是无法做到的。但问题不是特定于类模板。但是有些解决方法在某些情况下有效。
您可以使用boost::variant<>
做您想做的事情
boost::variant<int, float> v;
v = 0; // v is now storing an int
v = 0.f; // v is now storing a float
struct A {
typedef void result_type;
void operator()(int i) const {
// process the int
}
void operator()(float f) const {
// process the float
}
};
// If v stores an int, it calls the int version.
// Otherwise it calls the float version.
boost::apply_visitor(A(), v);
请参阅boost::variant。
您可以使用词法作用域来创建一个隐藏另一个名称的新变量。当您只希望名称更改其含义时,这可用,而不一定是前一个对象。一个重要的区别是,这只会在编译时改变一些事情。 boost::variant
能够在运行时跟踪其存储的类型。
int i = 0; // i now refers to an int variable
{
float i = 0.f; // i now refers to a float variable
}
// i refers again to an int variable.
希望它有所帮助。
答案 2 :(得分:1)
在C ++中,对象无法在运行时更改其类型。
然而,ere大致相当于一种可能性
template<class T>
struct Number {
template<class U> operator U(){
U temp;
// conversion code typically using casts e.g.
return temp;
}
};
这使您可以编写
等代码template<class T>
struct A{
template<class U> operator U(){
return U();
}
};
int main(){
A<int> a1;
float f1 = a1; // convert a1 to float equivalent and so on.
A<float> f2 = a1; // convert a1 of type A<int> to A<float>
}
答案 3 :(得分:0)
不,你不能。
但是你可能有一个非常尴尬的解决方案涉及union
/重载=
运算符,我还没有尝试过。所以我不能说它会起作用。
答案 4 :(得分:0)
以下是问题的直接答案。正如对这个问题的评论所表明的那样,知道你为什么要问它,即你想要达到的目标,这将是很有趣的。
正如Oli在他的回答中所写,C ++是静态类型的,所以不,变量的类型不能在运行时更改。
但是,如果您事先知道变量所需的类型集(来自示例int
和float
),则可以声明类型为“int或float”的变量。这是其他答案提到的union
解决方案。但是,union
有他们的怪癖并且非常容易出错。此外,仅靠联合通常是不够的,因为通常需要一些关于当前持有类型的信息。
来了Boost.Variant,这是一个“有区别的联盟”(一个“知道”它目前持有什么类型的联盟)。它允许你写一些类似的东西:
// Warning: off the top of my head, not compiled, less tested
boost::variant<int, float> int_or_float;
// Variants initialize by default as the first type in their list,
// so int_or_float is currently holding an int
assert(int_or_float.which() == 0);
int_or_float = 0.1;
// Now holding a float
assert(int_or_float.wich() == 1);