Onuchin Valeriy wrote: > Dear C++ experts, I have few questions about cast operation. Okay, a quick test on a compiler would have answered many of these questions. However, let us press on, since we all know compilers are never the answer, only the source of more questions. > class A > { > private: > Object* theGoal; > public: > Object* GetTheGoal() const { return theGoal; } > ... > }; Note that if you ever wish for there to be C::GetTheGoal() you should declare this method virtual, otherwise it "hides" and you get different behavior. And that's important. > class B; // some other class > class C: public A, public B // multiple inherited > { > ... > }; > B* d = new C(); > Object* goal1 = ((A*)d)->GetTheGoal(); // cast B to A > Object* goal2 = ((C*)d)->GetTheGoal(); // cast B to C Okay, that's the source code. Let's assume that you do *not* declare a method C::GetTheGoal. In that case, both operations will call A::GetTheGoal (there's no other option). Both will compile fine. BUT ... To clearly understand what's going on, stop using C-style casts. Use C++ casts. You will find that you would be forced to use: (reinterpret_cast<A*>(d))->GetTheGoal(); (static_cast<C*>(d))->GetTheGoal(); to compile. And you would clearly realize that you are doing a cast that means more than just syntax to the compiler. And that you are simply lucky because you do not have any virtual functions. A reintepreted cast is a dangerous thing. Let's throw virtuality into the mix. Change A::GetTheGoal() to be virtual, and declare and define C::GetTheGoal() to be different (so we can tell which is called). Now, when the compiler tries to do the reinterpret_cast<A*>(d) (or for that matter, the C-style cast), it seg faults because B and A are not related. It can't do it the runtime reinterpretation. It's illegal. Here's the very interesting example! virtual A::GetTheGoal exists. C::GetTheGoal also exists. C *d = new C; then: d->GetTheGoal(); and (static_cast<A*>(d))->GetTheGoal(); will *both* call C::GetTheGoal() !!! To see a But if you don't declare A::GetTheGoal as virtual, then: d->GetTheGoal() --> C::GetTheGoal(); (cast to A*)(d)->GetTheGoal() --> A::GetTheGoal(); Different behavior. Confused yet? Let's sum up: > 0. what cast from above is correct? You should do neither. Casting B to A is illegal - they are not related. Casting B to C is allowed, but should never be required (C inherits B and thus can be used anywhere B is allowed) because not only is that the point of inheritence, but can you guarantee that if someone passes you a B* it's pointing to C? What if I declare D inheriting B and pass you a D*?. Casting C down to B is allowed, but depending on the data passing type, you can "slice" off all the specific information to C and if you tried to cast back from B to C would get garbage. To quote Stroustrup: "If you feel tempted to use an explicit type conversion, take the time to consider if it is *really* necessary. In C++, explicit type conversion is unnecessary in most cases when C needs it and also in many cases in which earlier versions of C++ needed it." Oh, and the difference of static_cast<>() and reinterpret_cast<>() is the relation of types before and after the cast. A static cast would be something like enum to int; a reinterpreted cast like integer to pointer. > 1. if there are rules to avoid segmentation violation errors? Don't write illegal casts. :-) > 2. what is difference between declarations > class C: public A, public B > and > class C: public B, public A In QT or in C++ generally? In QT, it makes a difference to 'moc'. In C++ it mandates the order in which base classes are constructed (unless overridden by an initializer in a constructor). I think. Double-check. I avoid multiple inheritance wherever possible. > 3. if cast operation is platform/compiler dependent ? The C++ casts are a part of the C++ specification. What is p/c dependent is the way they are performed, especially when it comes to base and derived classes and vtbl lookups. -Michael -- Michael J. Saletnik Software Engineer, AutEx, TFS Boston
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:36 MET