a problem about static_cast

my code is bellow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class CBase { virtual void dummy() {} };
class CDerived: public CBase 
{ 
    int a; 
public :
    void hello() { cout << "hello" << endl; }
};

int main () 
{
    try {
        CBase * pbb = new CBase;
        CDerived * pd;

        pd = static_cast<CDerived*>(pbb);
        if (pd==0) cout << "Null pointer on second type-cast" << endl;
        (*pd).hello();
    } catch (exception& e) {cout << "Exception: " << e.what();}

    return 0;

}


I compile it in ubuntu with g++ 4.3.3
and run it, then I get result like bellow:
hello

My problem is that why it doesn't emit a error but run ok, the pd cast from pbb should point to an incomplete object, isn't it?
Change static_cast to dynamic_cast. Static don't check for you anything.
Last edited on
I know this, but my question is not about this. I want to know why I define a CBase object, but it can call the hello function, and it call that function successfully.
http://cplusplus.com/doc/tutorial/typecasting/

Read this carefully: it states that static_cast<>() can convert base class pointers to derived class pointers.

-Albatross
yangguosdxl:

It's just "luck" that it's working.

What's happening is the function is being called with a bad 'this' pointer. But since the function doesn't appear to be using the 'this' pointer, you don't experience any problems.

Try the same thing, but make 'hello' a virtual function. Then watch your program explode.

This is the danger of downcasting with static_cast. Note there's no compiler error, yet this is not legal to do! Very dangerous.
Disch:

I try what you say, and it run failed.Can you explain more detail for it?
Why it is ok when I use the normal function, but it failed when use the virtual function?

thank you
@Disch
You mean "evil".

-Albatross
Before I explain this I want to be sure that you READ MY NOTES AT THE BOTTOM, as I don't want to mislead you.

Consider the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct Foo
{
  int a;
};

void Func1(Foo* f)
{
  cout << "Func1\n";
}

void Func2(Foo* f)
{
  cout << "Func2 Enter\n";
  f->a = 6;
  cout << "Func2 Exit\n";
}

//======

int main()
{
  Foo* f = 0;  // a bad pointer

  Func1(f);
  Func2(f);

  return 0;
}


Look what happens here. Func2 will explode on the f->a = 6; line for obvious reasons (f is a bad pointer), but Func1 will run just fine, even though f is a bad pointer.

The reason Func1 runs fine is because 'f' is never used in Func1. Therefore it doesn't matter that the pointer is bad.

non-virtual member functions in C++ basically operate the same way under the hood. The compiler just changes the syntax around a bit. It's basically like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// this code here:
struct Foo
{ int a; };

void PrintA(Foo* f)
{
  cout << f->a;
}

//...
Foo* f;
PrintA(f);

// is pretty much the exact same thing as this code here:
struct Foo
{
  int a;
  void PrintA()
  {
    cout << this->a;
  }
};

//...

Foo* f;
f->PrintA();


In the f->PrintA(); example, 'f' is passed to the function as a parameter, just like it would be normally... only the compiler sort of hides that from you. 'f' becomes the 'this' pointer in the function. So when you cout this->a you're really outputting f->a.

Note that if 'this' isn't used, there's no problem.... as is the case in the Func1 example in this post, and the bad cast example in your original post. Both work just fine because the bad pointer is never used.


virtual functions, on the other hand, always use the this pointer (they have to in order to use the vtable to determine which class's function to call), which is why your original program explodes when you change 'hello' to be a virtual function. The bad pointer is now being used... and since it's bad, it causes problems.


==================================================
READ THESE NOTES
==================================================

My above examples are conceptual only. And while they may compile and run as you expect on your compiler, the C++ standard does not say that must always be the case.

It is theoretically possible for non-virtual functions to use the 'this' pointer somehow without you knowing it... therefore this is never safe to do
Topic archived. No new replies allowed.