C++中从用户定义类型到基元类型的隐式转换
Implicit conversion from user-defined type to primitive type in C++
我能够找到大量关于从int到用户定义类型的隐式转换的信息。即,如果构造函数将int作为其参数,并且没有以"显式"开头,则可能发生隐式转换。
如果我希望我的类隐式地将转换为一个int,该怎么办?
例如,需要在SimpleClass内部或外部添加什么函数,以便主函数编译并向控制台输出"1"?(见评论)
#include <iostream>
class SimpleClass
{
private:
int m_int;
public:
SimpleClass(int value)
: m_int(value) {}
};
int main(int argc, const char * argv[])
{
SimpleClass simpleclass(1);
int i = simpleclass; // does not complile
std::cout << i << std::endl; // should output "1" to the console
return 0;
}
隐式转换可以用两种方式定义:
- 非显式单参数构造函数
- 非显式转换函数(也称为转换运算符),N3337 12.3.2
后者允许定义从类类型到基元类型的转换。只需添加
class SimpleClass {
// ...
operator int() const;
};
SimpleClass::operator int() const
{
return m_int;
}
技术
可以通过operator T
成员函数来执行到(几乎)任何类型的T
的转换。
默认情况下,它是隐式调用的,如果您声明它为const
,它也可以在const
对象上调用。
因此:
struct MyType
{
operator int() const { return 1; }
};
问题…
具有到基本类型的隐式转换允许所有内置运算符自由发挥,包括
- 算术运算符
- 布尔运算符
- 关系运算符
所以你最好确保所有这些都按照你想要的方式运行。
这可能是一项艰巨的工作!
对于涉及您类型实例的调用,重载解析也存在潜在问题。
简言之,隐式转换为int
、指针或任何内置类型的成本通常高于其价值。
当一个类在库中被大量使用时,它是有价值的。
你能做些什么
避免隐式转换,但要提供显式转换。
最好的通用显式转换是命名成员函数IMHO。
另一种选择是前缀为关键字explicit
的operator T
,它在C++11及更高版本中支持使用(在C++03中,它只能用于构造函数)。
如果您希望通过<<
的输出表现为执行了隐式转换,那么只需定义一个operator<<
。
同样,对于其他情况,隐式转换似乎是一种通用的解决方案:只需定义适合该特定情况的内容,避免引入通用的隐式转换。
提供到内置类型的隐式转换,同时避免“免费";对于内置运算符,可以使用模板化的类型转换,例如:
#include <iostream>
template< class A, class B > struct Is_t_;
template< class Type > struct Is_t_<Type, Type> { using T = void; };
template< class A, class B >
using If_is_ = typename Is_t_<A, B>::T;
struct Bad_string
{
operator const char* () const { return "666!"; }
Bad_string( char const* = 0 ) {}
};
auto operator==( Bad_string const&, Bad_string const& )
-> bool
{ return true; }
struct Good_string
{
template< class Type, class Enabled_ = If_is_<const char*, Type>>
operator Type() const { return "42 :)"; }
Good_string( char const* = 0 ) {}
};
auto operator==( Good_string const&, Good_string const& )
-> bool
{ return true; }
#if defined( DO_GOOD )
using String = Good_string;
#elif defined( DO_BAD )
using String = Bad_string;
#else
# error "Define either DO_GOOD or DO_BAD, please."
#endif
auto main() -> int
{
String a, b;
(void) (a == "alfalfa"); // Errs for Bad_string
(void) (a + 1); // Compiles for Bad_string.
}
具有讽刺意味的是,当定义DO_GOOD
时,此代码会使Visual C++2015更新1编译器崩溃,即所谓的“ICE";(内部编译器错误)。
该编译器的一个变通方法是将If_is_
定义为
template< class A, class B >
using If_is_ = std::enable_if_t< std::is_same<A, B>::value >;
要允许将类转换为int
,请实现
operator int() const
{
return m_int;
}
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 事件系统:使用类型转换或联合进行继承
- 如何在参数中定义隐式类型转换的构造函数?
- 类模板实例化中的类型转换