我有一个 Value
可以保存各种数据类型的值的类。
class Value
{
private:
union
{
int Integer;
double Real;
bool Boolean;
};
ValueTypes valType;
public:
Value();
Value(double Val);
Value(int Val);
Value(bool Val);
/* ... */
friend std::ostream& operator <<(std::ostream& stream, const Value& val);
}
我想重载 <<
运算符,因此可以打印值而无需调查其类型。
这是我当前的实现:
std::ostream &operator <<(std::ostream &os, const Value &val)
{
switch (val.valType)
{
case ValueTypes::Real:
os << val.Real;
break;
case ValueTypes::Integer:
os << val.Integer;
break;
case ValueTypes::Boolean:
os << (val.Boolean ? "True" : "False");
break;
}
return os;
}
首先,当使用 g++(CodeBlocks IDE、Ubuntu)编译时,实现会导致隐式转换为 Value
。 .当值类型是 Integer
时或 Real
, os <<
语句将它们转换为 Value
,然后调用 ostream
再次重载(无限递归),所以我最终遇到了段错误。
其次,当用 Visual C++ 编译时,隐式转换消失了,它打印的值很好(不调用隐式构造函数)。
注释:
我希望保留隐式构造函数,因为它增强了可读性并简化了我项目其他部分的维护。
此外,我还发现了以下blog post , 但未能调整我的代码使其按我希望的方式执行(模板的使用有点超出我目前对 cpp 语法的理解)。
我该怎么做才能在特定的 ostream
中禁用隐式转换?重载函数?
编辑:
与 -Wall
已启用,我在 CodeBlocks 中没有收到任何警告。
最佳答案
您需要 #include <ostream>
.没有它就不能工作的原因是因为这是实际定义 std::ostream
的 header 。以及所有有用的 operator<<
功能。
它没有 panic 并提示“没有定义 std::ostream
”(或其他 <<
运算符)的原因是前向声明。如果您转发声明一个类型,您可以将它用作指针或引用(只要您不尝试进一步访问它)。 You can do some things with an incomplete type .
您包含的其他 header 可能是前向声明 std::ostream
, 但从未给出它和所有 <<
的完整定义运营商。至少在你的 Ubuntu 系统上。在其他系统上,其他 header 可能包含 <ostream>
或者至少提供了一些 <ostream>
的定义做。你的operator<<
可能是编译器看到的唯一一个(因为您没有包括 <ostream>
),并且由于它是编译器唯一知道的一个,它试图将它用于所有事情。
简而言之,在处理跨平台内容时,应该小心翼翼地包含确切的必要内容(而不是依赖其他 header 来包含与其无关的内容)。
关于c++ - 选择性隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22585270/