Okey, let me change the function main a little bit,
This time it works. It looks like I can design my conversion operator as a dynamic_cast operator.Code:int main()
{
D* pD = new D;
B& b = *pD;
test(b);
delete pD;
return 0;
}
Printable View
What you have done is implement your conversion function to perform a dynamic_cast. Anyway, what's your point?Quote:
Originally Posted by LarryChen
No. The conversion function could be implemented with a dynamic_cast, reinterpret_cast, or it might not even use a cast at all, but in any case, one would just use it either without a cast (if it is not explicit) or with a static_cast (if it is explicit, or if you wish to emphasize that there is a conversion).Quote:
Originally Posted by LarryChen
Okay, LarryChen, since you love your dynamic_cast "counterexample" so much, consider this contrived example:
Compile and run this program. An address should be printed. Now, change the static_cast to a dynamic_cast and attempt to compile. Does it compile? Why not?Code:#include <iostream>
class Z;
class Y
{
public:
operator Z*();
virtual ~Y() {}
};
class Z : public Y {};
Y::operator Z*()
{
return dynamic_cast<Z*>(this);
}
int main()
{
Z z;
Y& y = z;
std::cout << static_cast<Z*>(y) << std::endl;
}
As monarch_dodra noted in post #27, this is a C++11 feature. Previously, the common approaches would be to either allow the implicit conversion, which can be problematic, or use a named conversion function instead (e.g., std::string's c_str() function), or for conversion to bool, provide a conversion to void* instead or use the safe bool idiom.Quote:
Originally Posted by LarryChen
It's a part of the C++ language, a language feature, "dynamic_cast" is keyword, etc.
Have you read this?
The way I understand it, the whole point in having various cast operators (aside from the fact that they were designed to scare you away from using them) is to use a different one in different situations, and express (via your choice) what is it that you're doing. Although, as I said, I personally think such language design is a bit over the top, but hey... People don't have to agree on everything.
Converting to and from hierarchically unrelated types aside, it is also important to understand inheritance, in order to see what some of the operators are doing or are designed for. Namely, inheritance (in the general OO sense, C++ particularities aside) models "is-a" relationship between types (every Dog is-an Animal, but not the other way around).
Another thing to consider is if a (base) class is polymorphic or not, in the strict sense. In C++, it means if it has virtual methods that can be overridden in a derived class.
So, if B is base, and D is derived, you can safely (up)cast from D to B (Dog to Animal), but things get interesting if you want to cast from B to D (Animal to Dog - either the Animal is actually a Dog, or it's something else, say a Cat).
With dynamic_cast, if B is not polymorphic, the compiler will complain, which is IM(H)O, rather aggressive - but that's how the whole thing is designed.
If it is polymorphic, you get to check, at runtime, if you B really is D or not (if not, you get a null pointer, or an exception).
Next, while the article I linked to deemed static_cast useless, I disagree: if you know what's the actual type of the object, you don't need dynamic_cast and RTTI, and static_cast nicely states that. And it doesn't care if the class is polymorphic or not.
It's designated as less safe, but only if you're pulling stunts with it.
You're also avoiding runtime type check overhead of dynamic_cast.
Finally, reinterpret_cast simply does a "binary copy of the value from one pointer to the other". So, using it would seem to communicate to whoever is reading your code that you have rather specific intentions, or, alternatively, that you are really trying to mess with the code.
P.S. Again, I'm not exactly a C++ dev (I just hopped here from C# forums), so if guys you have any objections to share, please do; a chance for me to learn something myself.
Sry, not that article, but the one that advocates C-style casts, a few posts back.
Edit: here - #8.
It proves that blindly substituting a dynamic_cast for a static_cast just because the conversion function is implemented with dynamic_cast is a wrong thing to do.Quote:
Originally Posted by LarryChen
Besides, I am merely stating what is the expected practice (refer to my post #34). If you want to do something else, go ahead, but don't blame me if your code ends up getting ridiculed by those who read it.
If you insist, why not show an example program in which invoking a conversion function implicitly or with static_cast does not make sense, whereas using dynamic_cast or reinterpret_cast to invoke that conversion function works and makes sense?
Certainly. But now, a reader reading your code would ask why you used dynamic_cast rather than static_cast. What is your reply?Quote:
Originally Posted by LarryChen
Another reader reading your code would ask why you implemented the conversion function when using dynamic_cast directly would do the job. What is your reply?
EDIT:
If you want something from the standard, take a look at C++11 Clause 12.3.2, the one on conversion functions. In note 116 of that clause it states that "these conversions are considered as standard conversions for the purposes of overload resolution (13.3.3.1, 13.3.3.1.4) and therefore initialization (8.5) and explicit casts (5.2.9)". Guess what? Clause 5.2.9 is about static_cast.
Yes, unless the conversion function is declared explicit, or for some reason you really want to emphasize that there is this conversion that is happening. Again, I already stated this in post #34.Quote:
Originally Posted by LarryChen