Solved

Casting question

Posted on 2002-05-10
11
232 Views
Last Modified: 2010-04-02
Can someone tell me what technically happens in memory when I cast one object to another. As an example, there are many situations in MFC where I can cast one object to the another type and can call the member functions of the second type. Obviously, I have a vague notion of what's happening here, but I'd like a detailed description. Because of that I'm offering 200 points and will offer much more for a link to a graphical illustration as well.
0
Comment
Question by:tma050898
  • 5
  • 3
  • 2
  • +1
11 Comments
 
LVL 30

Expert Comment

by:SteveGTR
ID: 7001255
I'll open this up by saying nothing happens in memory when you cast an object from one to another. You are simply instructing the compiler that the memory pointed to by one object is actually an object of this type so don't complain about it. Once this is done you can (correctly or incorrectly) reference the object's attributes, ie. class members, functions, structure members, whatever.
0
 
LVL 16

Expert Comment

by:AlexNek
ID: 7001256
2 tma
>what technically happens in memory when I cast one object to another.
Nothing. Object casting it is only way to say compiler what it allowed to do with pointer.
Class A
{
  f1();
}
Class B : public A
{
  f2();
}

A* pa;

pa = new A;    // pa = 21234567 by sample
pa->f1();      //1. it is allowed for compiler
pa->f2();      //2. it is not allowed for compiler
((B*)pa)->f2() //3. is is allowed for compiler. pa = 21234567 the same value

In case 1 compiler call function xxf1xx(pa) where first parameter pa is "invisible" for programmer (Often it is first parameter). C++ compiler used internal function name for this reason I used xxf1xx() not f1().

In case 3 compiler call function xxf2xx(pa) with the same parameter pa.

If you know what is virtual pointer table I can give you the next sample.
0
 
LVL 3

Author Comment

by:tma050898
ID: 7001305
SteveGTR,

When I say something taking place in memory what I mean is that obviously some type of mapping is occurring for me to be able to cast one type to another type with both types based on the same base class and then cast to the second type. Maybe it's a simple as the compiler pointing me to the second types vtbl and with the two classes having the same vtbl layout in memory (up to the point that their derivation chain diverges) it works. This what I'd like to know for sure.
0
 
LVL 3

Author Comment

by:tma050898
ID: 7001308
Alex,

Yes, having quite a bit of COM experience I know what the vtbl is. Take a look at what I wrote Steve. Is this close to what happens? Please do post the example you referred to.
0
 
LVL 30

Expert Comment

by:SteveGTR
ID: 7001337
Check out http://java.sun.com/people/inder/Gray-article.html for more information.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 3

Author Comment

by:tma050898
ID: 7001354
So if I understand this page, I am correct in that when you cast all that is happening is that the compiler points to a different class layout in memory and if they align to the point that they need to for the specified particular member all is well?

For example, let's say I have the following base class:

class CWnd
{
public:
 CWnd() : m_hWnd(42) {}
protected:
 DWORD m_hWnd;
};

class CDialog : public CWnd
{
public:
 void DoSomething()
 {
  CString str;
  str.Format("HWND = %ld", m_hWnd);
  AfxMessageBox(str);
 }
}

class CFormView : public CWnd
{
}

Now let's say I do the following because I want to use the DoSomething function.

CFormView pFV = new CFormView();
((CDialog*)pFV)->DoSomething();

The question is why does this work and I think it works because the memory layouts of both classes is indentical insofar as the m_hWnd member definition is concerned. Therefore, when the compiler casts my pFV to a CDialog and calls its member function my pFV has a valid value there.

However, I'm a bit sketchy on the details of how all this looks and works in memory and was looking for confirmation or correction.

0
 
LVL 16

Expert Comment

by:AlexNek
ID: 7001526
2 tma
First, you are allowed to cast only object in the same hierarchy path. Because CDialog inheritance paht has no intersection with CFormView inheritance path your type casting is wrong. In some cases this casting can look as working one.

I try to expand my sample for your case
class A
{
 f1();
}
class B : public A
{
 f2();
 int test;
}
class C : public A
{
  f3();
}

C *pc;
ps = new C;
pc->f3();       //1. correct
pc->f1();       //2. correct
pc->f2();       //3. incorect. Wrong iheritance path
((B*)pc)->f2(); //4. incorrect but can work.

Compiler for 4 can call xxf2xx(pc). If function f2 used "this" pointer for access to data member or virtual function you can have a crash because function f2 expected "this" pointer as pointer to class B not to class C. By sample if function f2 used data member test;
Why? For data member access you need to know (often) offset from "this" to data member. For class C compiler allocate not so much memory as for class B and when function try to access memory outside allocated space we don't know what happens.
0
 
LVL 3

Author Comment

by:tma050898
ID: 7001631
>>>
First, you are allowed to cast only object in the same hierarchy path. Because CDialog inheritance paht
has no intersection with CFormView inheritance path your type casting is wrong. In some cases this casting
can look as working one.
<<<

Actually, this is exactly what MFC does in many cases hence my question about what technically casting is doing under the covers. I've got to run, but thanks for the input. I'll look at the rest of your sample as soon as I get back.
0
 
LVL 16

Expert Comment

by:AlexNek
ID: 7001856
2 tma
>Actually, this is exactly what MFC does
Compiler don't check if cast is allowed like ((B*)pc. If you want this use dynamic_cast<B*>(ps). This call controlled by RTTI and you have NULL as result with wrong type casting.

Here is the simplified sample for virtual functions:
class A            //vptrA[0] = f1
{
  virtual f1();
}
class B : public A  //vptrB[0] = f1, vptrB[1] = f2
{
  f0() {f2(); }
  virtual f1();
  virtual f2();
}
class C : public A // vptrC[0] = f1
{
  virtual f1();
}
C *pc;
ps = new C;
pc->f1();       //1. correct
pc->f2();       //2. incorect. Wrong iheritance path
((B*)pc)->f0(); //3. Syntax correct but wrong.
((B*)pc)->f2(); //4. Syntax correct but wrong.

3. Compiler can call xxf0xx(pc). In function xxf0xx compiler try to get vptr and get vptrC but not expected vptrB. In the next step it call function vptrC[1] - execution error.
4. Compiler tries to get vptr and get vptrC but not expected vptrB. After function call vptrC[1] - execution error.

If you know assembler, try to look in assembler code of your program. You can find many interested details.
0
 
LVL 22

Accepted Solution

by:
ambience earned 200 total points
ID: 7007633
OK, i remember another question like this asked recently

http://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=cplusprog&qid=20291350

I bet that one would answer your doubts, here is what casting is all about. First casting is just some arithmetic involved on part of the compiler.

class A
{
public:
 int a;
};

class B: public A
{
public:
int b;
};

A *p = 0;
B b;

pB = & b;
pA = (A*) pB;  

What really happens is that the compiler adds a +/- offset to the pointer to B and "reinterprets" the resulting value as a pointer to A.
This kind of cast is what you know as a static cast in C++.

Now something about the offset, the value of the offset depends upon the internals of A and B i.e. memory layout of A and B. Member or nested classes inside a class change the value of that offset. I hope you already know how the objects are laid out in memory , as this is the key to casting. Im not getting into the details now as it is a detailed topic in itself.

You can actually see that happening by simply displaying the value of the pointer before and after the cast. In most cases of simple inheritance this is usually zero, but try some multiple inheritance and you'll see it. HINT: try using virtual inheritance !!

>> what technically happens in memory when I cast one object to another.
>>Nothing. Object casting it is only way to say compiler what it allowed to do with pointer.

I donot agree that nothing happens at all, given what i have said above most of the times nothing happens but sometimes arithmetic happens.

That was the physical aspect of casting (static cast) , i hope it is clear now what reinterpret_cast is , because reinterpret_cast forces the compiler not to compute that offset value and simply reinterpret the pointer as pointer to something else, this is why it is a very dangerous cast and should only be used when you really know you should.

The other aspect of casting is more of logical nature where the compiler applies usual access rules and apply other inheritance semantics.

I hope this is clear now.
0
 
LVL 3

Author Comment

by:tma050898
ID: 7007649
Thanks much! Your answer was exactly what I wanted. It was one of those thing where I've enough experience in C++ (almost 10 years) to know something happens, but didn't know exactly what. What can I say? I can't stand "kinda knowing" something. I just had to know more detail :)

Thanks for the help!
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now