static_cast - Why does this work?

Note the line with the //*****WHY**** comment.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

class Base;
class Derived;

Base* pBase = NULL;

class Base{
	public:
		Base(){
			pBase = this;
		}

		virtual void sayHi(){ std::cout << "Base Class: Hi" << std::endl; }
};

class Derived : public Base{
	public:
		Derived() : Base()
		{}

		void sayHi(){ std::cout << "Derived Class: Hi" << std::endl; }
		void sayHiSpecial(){ std::cout << "Derived Class: Special Hi!" << std::endl; }

};

int main(){

	Derived d;
	pBase->sayHi();
	static_cast<Derived*>(pBase)->sayHiSpecial();

	std::cout << pBase << std::endl;
	std::cout << static_cast<Derived*>(pBase) << std::endl;

	Base b;
	pBase->sayHi();
	static_cast<Derived*>(pBase)->sayHiSpecial(); //******WHY****

	std::cout << pBase << std::endl;
	std::cout << static_cast<Derived*>(pBase) << std::endl; 

	system("PAUSE");
	return 0;

}


I don't understand how I am allowed to call sayHiSpecial() on a Base object? I was expecting a run time error.

Can anyone explain why this is happening?

Thx. Nick.

This code is horribly messy and dangerous. The whole idea of pBase being a global that Base modifies is just.... ugh.


I don't understand how I am allowed to call sayHiSpecial() on a Base object? I was expecting a run time error.


You're getting [un]lucky.

It just so happens that since sayHiSpecial doesn't use the this pointer, the program doesn't explode when you call the function. It's sort of like doing this:

1
2
3
4
void sayHiSpecial(Derived* foo)
{
  std::cout << "Derived Class: Special Hi!" << std::endl;
}


Even though you're passing a pointer to the function, it's never used, so it doesn't matter whether the pointer is valid or not.

That's what's happening in your code. You're passing a bad 'this' pointer to the function, but since 'this' is never used, it's not a problem.

This is still "very bad" though, because there's no guarantee that 'this' isn't used somehow. Like I said, you're just getting [un]lucky.

You could even do this:

1
2
3
Derived* d = 0;  // a null pointer
d->sayHiSpecial();  // wtf?  but it might work here for the same reason
  // but still bad to do!  Don't do it in your programs! 




If you want to see it explode, make sayHiSpecial a virtual function. That will make it so the this pointer is required (for vtable lookup). Then you'll get the runtime error you expected.
Last edited on
Haha thanks for that Disch. I wrote the above code to help me explore a design I was working on. Here is some more code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Base{
  public:
    Base() : pSomething(new Something(this)) {}
    Base(Derived* pDerived) : pSomething(new Something(pDerived)) {}
  protected:
    Something* const pSomething;
}

class Derived : public Base{
}

class Something{
  public:
    Something(Base* pBaseArg) : pBase(pBaseArg) {}
    Something(Derived* pBaseArg) : pBase(pBaseArg) { //Set some flag so that this knows it belongs to a Derived object.
  private:
    Base* pBase;
}

int main(){
  Derived d;
}


See how I have overloaded the Base constructor? I didn't want to do that. I need 'Something' to know when it belongs to a Derived object. However when Derived calls the Base class constructor, the Base class constructor passes "a Base 'this'" - instead of a Derived this. Overloading was the only way I could think about overcomming this. Ofcoarse if the object is just a Base then I would want it to pass a Base 'this'. Kind of tricky to explain.

Anything dangerous/stupid about this?
Last edited on
Well your code doesn't work like I think you intended. The overloaded Derived* ctors are never called.

You're jumping through hoops to do quesitonable things, anyway.

The whole idea of deriving classes and polymorphism is that you don't need to know whether or not an object is of a derived type. The "is a" relationship is what you're going for.

For example, let's illustrate this with the below:

1
2
3
4
5
6
7
8
9
10
11
class Dog
{};

class Poodle : public Dog  // A Poodle "is a" Dog
{};

class DogWalker
{
public:
  DogWalker(Dog* dogtowalk);  // a DogWalker walks dogs
};


The idea here is that you can write code for 'DogWalker' so that he can walk ANY Dog, not just Poodles. DogWalker doesn't even need to know the different kinds of dogs (and it shouldn't -- because that would make maintanance more difficult). The whole point is that you write the code once, and it will work for any and all Dogs that may be created in the future.

In your example you're trying to have your Something class figure out what derived type it's working with. While this is sometimes necessary, it's actually quite rare to have to do this. And it sets off red flags in my brain like you're doing something you shouldn't.

What exactly are you trying to accomplish? Forget about the Base/Derived/Something classes and tell me the actual classes you're working with and what they represent (and why you feel you need to know whether or not you have a derived instance). There must be a way to design this better.
Last edited on
Topic archived. No new replies allowed.