问题
Is it possible to override (C-style) casts in C++?
Suppose I have the code
double x = 42;
int k = (int)x;
Can I make the cast in the second line execute some code I wrote? Something like
// I don't know C++
// I have no idea if this has more syntax errors than words
operator (int)(double) {
std::cout << "casting from double to int" << std::endl;
}
The reason I ask is because of the question "Is there any way to get gcc or clang to warn on explicit casts?" and my suggestion there.
回答1:
§ 12.3.1/1 "Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9)."
Yes, we can make conversions, but only if one or both sides is a user-defined type, so we can't make one for double to int.
struct demostruct {
demostruct(int x) :data(x) {} //used for conversions from int to demostruct
operator int() {return data;} //used for conversions from demostruct to int
int data;
};
int main(int argc, char** argv) {
demostruct ds = argc; //conversion from int to demostruct
return ds; //conversion from demostruct to int
}
As Robᵩ pointed out, you can add the explicit keyword to either of those conversion functions, which requires the user to explicitly cast them with a (demostruct)argc or (int)ds like in your code, instead of having them implicitly convert. If you convert to and from the same type, it's usually best to have one or both as explicit, otherwise you might get compilation errors.
回答2:
Yes, but only for your own types. Look at this:
#include <iostream>
struct D {
// "explicit" keyword requires C++11
explicit operator int() { std::cout << __FUNCTION__ << "\n"; }
};
int main () {
int i;
D d;
//i = d;
i = (int)d;
}
So, you cannot create double::operator int(), but you could create MyDouble::operator int().
回答3:
You can’t overload operators for built-in types, but you can write a conversion operator for a user-defined type:
struct Double {
double value;
operator int() const {
shenanigans();
return value;
}
};
Since your question arose from a need to find explicit casts in code, also be aware that C++ has explicit casting operators. These are not only clearer than C-style casts, but also eminently searchable:
static_cast<T>(x) // Cast based on static type conversion.
dynamic_cast<T>(x) // Cast based on runtime type information.
const_cast<T>(x) // Add or remove const or volatile qualification.
reinterpret_cast<T>(x) // Cast between unrelated pointer and integral types.
回答4:
Conversions to other types are overloadable operators in C++ (some examples here), but this fact will not help you.
Stroustrup wanted the language to be extensible, but not mutable. Therefore, overloading an operator only extends the operations to new types, but you cannot redefine what happens with any old types.
"However, to avoid absurdities, it is (still) not allowed to provide new meanings for the built-in operators for built-in types. Thus, the language remains extensible but not mutable."
来源:https://stackoverflow.com/questions/10320282/are-casts-overridable-operations-if-so-how