Click here to Skip to main content
15,885,366 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Dear,

Thanks in advance.
I am working on C++ project in DevC++ environment. I am wondering how following program is working fine?

C++
#include <iostream>
using namespace std;

class Base{};
class Derived1:public Base{};
class Derived2:public Base
{
      public:
             float Derived2Data;
             void Derived2Fun(){}
      void Derived2Fun1()
      {
           Derived2Data = 10.9;
      }
};

void main()
{
      Derived1 obj2;
        Base* pBase1 = &obj2;
        ((Derived2*)pBase1)->Derived2Fun(); // no error
        ((Derived2*)pBase1)->Derived2Fun1(); // no error
        cout<<"Value of Derived2Data is:"<<((Derived2*)pBase1)->Derived2Data<<endl;
}



Output: Value of Derived2Data is: 10.9

even though this is a wrong typecasting. upcasting->cross-downcasting. even then there is no run-time as well as compilation error. it may cause disasters, this is very unsafe?
Posted
Updated 9-Feb-12 1:22am
v2
Comments
Richard MacCutchan 9-Feb-12 7:30am    
I don't know the answer, but I wonder if it is because Base and Derived1 are empty classes? What happens if you put some actual code inside them both?
Stefan_Lang 9-Feb-12 7:59am    
This is not multiple inheritance at all.

// I am wondering how following program is working fine?

Please put also the sizesof(Derived1 obj1) and sizeof(Derived2 obj2) out ;)
 
Share this answer
 
Comments
ggupta2009 9-Feb-12 7:36am    
Hi,

I have added following inside main()

Derived2 obj3;
cout<<"size of Derived1 class is: "<<sizeof(Derived1)<<endl;
cout<<"size of Derived1 class object is: "<<sizeof(obj2)<<endl;
cout<<"size of Derived2 class is: "<<sizeof(Derived2)<<endl;
cout<<"size of Derived2 class object is: "<<sizeof(obj3)<<endl;

Output:
Value of Derived2Data is: 10.9
size of Derived1 class is: 1
size of Derived1 class object is: 1
size of Derived2 class is: 4
size of Derived2 class object is: 4
Eugen Podsypalnikov 9-Feb-12 7:47am    
So the casting has just "extend" (incorrect)
the boundary of a smaller object by the data member of the bigger type :)

There could lie another application data,
but your test had a lucky end (not a low) :)

When you try to extend the smaller object by a float member as well,
the "casted" set method will set it (not the original member) :)
First of all, using C-style typecasts on C++ types is a very bad idea. Use dynamic_cast, static_cast, etc. instead (and make sure you know exactly when to use which: see http://www.cplusplus.com/doc/tutorial/typecasting/[^] )

Second, without virtual functions, inheritance doesn't make sense. But I'll assume for now this is just an oversimplifaction on your part to focus on the code in question. [edit]does not relate to the question - please ignore[/edit]

Third, C style typecasts will always be accepted by the compiler: they basically tell the compiler that you know better than the compiler does. (IME this is very often a misconception, and in this case it definitely is)

Last, this works because you were lucky: What happens here is that on the stack, an object of type Derived1 is created, with the appropriate size to fit such an object. Then, you the compiler that in truth this is an object of type Derived2 instead. Because you used C-style typecasting the system will comply to your wish without question and overlay the memory layout of Derived2 over the memory occupied by obj2. This will work for as long as you don't try to use virtual functions, or data members, but when you call Fun1(), you actually write into a data member: Since the memory orginally allocated is not big enough to fit Derived2, you're writing outside the bounds of that memory.

Normally, this causes other variables to be corrupted, but it seems that you were lucky in this case. I believe that internally, the stack variables are stored in reverse order of declaration: in this case pBase first, then obj2. If it had been the other way round, you would have overwritten pBase1 and the last line of your code would likely have crashed,
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 9-Feb-12 23:49pm    
"Second, without virtual functions, inheritance doesn't make sense." is totally wrong. I did not vote; recommend to fix this ridiculous statement. I you say this has little to nothing to so with "real OOP", I'll readily agree, but "doesn't make sense" is unforgivable exaggeration.
I hope I won't need to explain where it is useful...
--SA
Stefan_Lang 10-Feb-12 5:20am    
You are correct, in theory. In praxis however, not defining a virtual destructor for every C++ class at the very least is an invitation for desaster: You can get away without one if you never derive another class from that class, but since there is no built-in mechanism to prevent inheritance, you can never know when, in the future, another class will be derived from any existing one.

Of course, you will not notice the lack of a virtual destructor if you never downcast a pointer (implicitely or explicitely) from a pointer to a derived class. However, if you never downcast, what then was the purpose of creating the hierarchy in the first place?

I'm not saying that you can't create an arbitrary hierarchy of classes without any virtual functions. Obviously you can. I just say that if you do, something is seriously wrong in your design. That's what I meant when I said "doesn't make sense".

Would saying "this has nothing to do with real OOP" make any difference? If any, then only the implication that it's fine to use C++ even if you stick to procedural paradigms. I beg to disagree with that: someone who is concerned enough to ask about the consequences of certain forms of inheritance, even multiple inheritance, should be very aware of the paradigm behind OO languages. Ignoring it is a grave mistake.

P.S.:
Since this point does not actually relate to the question and apparently doesn't help without the benefit of an exhaustive explanation, I updated the solution to remove it.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900