[英]Implicit conversion from user-defined type to primitive type in C++
我能夠找到大量有關從 int 到用戶定義類型的隱式轉換的信息。 即,如果構造函數采用 int 作為其參數,並且沒有以“顯式”開頭,則可能會發生隱式轉換。
如果我希望我的類隱式轉換為int 怎么辦?
例如,需要在 SimpleClass 內部或外部添加什么函數,以便 main 函數編譯並輸出“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;
}
隱式轉換可以通過兩種方式定義:
后者允許定義從類類型到原始類型的轉換。 只需添加
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
、指針或任何內置類型的成本通常高於其價值。
一個值得使用的例外是在庫中大量使用類時。
避免隱式轉換,但提供顯式轉換。
最好的通用顯式轉換是,恕我直言,一個命名成員函數。
一個替代方法是一個以關鍵字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 update 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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.