-1

What is the preferred method for initializing a derived class that was casted from it's base class?

Consider the following scenario:

    class A{
        public:
           A();
           ~A();
    }

    class B : public A{
        public:
           B() {m_b = 0.0;};
           ~B();
           float GetValue(){return m_b;};

        private: 
           float m_b;
    }


    A* a = new A;
    B* b = static_cast<B*>(a);

    float val = b->GetValue();   // This was never initialized because it was not constructed

My current solution is to manually call an Initialize() function which would perform the necessary initializations as the constructor would.

It seems sloppy though and there must be a better/cleaner method.

Any help and guidance is greatly appreciated!

sbi
  • 219,715
  • 46
  • 258
  • 445
Hank
  • 25
  • 6
  • Matt, that `GetValue()` function should be `const`, since it doesn't alter the state of the objects it's invoked on: `float GetValue() const {return m_b;};`. What are you learning C++ from? Have a look at [this FAQ entry](http://stackoverflow.com/questions/388242/). If you can learn from one of those books. – sbi May 11 '11 at 20:29
  • And one more thing: Casting to a derived class from a base class pointer/reference is frowned upon, and for good reasons. Why do you think you need that anyway? Your class names and minimalistic implementations (no critique, it's a great repro!) give no hints as to why you designed it that way, but I'd question such a design. Have you programmed in any OO language before? – sbi May 11 '11 at 20:33

6 Answers6

5

This is a faulty construct:

A* a = new A;
B* b = static_cast<B*>(a);

EDIT

It should really be:

B* b = new B();

Since, as sbi pointed out, A does not have a virtual function called GetValue(), so it can never be invoked from A.

Do not do a static_cast from A* to B*.

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • Actually you need to cast `a` to a `B *` since `GetValue` is `B` specific. [now why one would design the classes like this is another story] – Eugen Constantin Dinca May 11 '11 at 15:51
  • The problem is not in the casting as this answer would have you believe. Joe Gauterin identified the proper problem in that B was not being instantiated and that a copy constructor B(A) was required. – Hank May 11 '11 at 18:19
  • @Matt that is no different to what I said. read what my answer says, I"m creating a B right there!! No Copy ctor is needed here, since your class contains no pointer members – Tony The Lion May 11 '11 at 18:22
  • 2
    @Matt : The problem **is** in the casting, since the casting you've shown invokes [undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior). – ildjarn May 11 '11 at 20:02
  • @Tony: This is wrong. You cannot invoke `B::GetValue()` through an `A*`, since it's not declared `virtual` in the base class. In fact, it's not in the base class at all, so `a->GetValue()` is a syntax error. – sbi May 11 '11 at 20:30
2

You are casting a parent object into an object of a derived type. That is plain wrong. An object of class A does not have an m_b member to initialise.

0

I'm not sure this is valid at all, because the object was created with sizeof(A) and sizeof(B) is clearly larger.

Dan F
  • 17,654
  • 5
  • 72
  • 110
0

The code you described is dangerous and not valid, since B is A, but not the other way around. This would be valid:

B* b = new B;
A* a = dynamic_cast<A*>(b);
JoeG
  • 12,994
  • 1
  • 38
  • 63
Constantinius
  • 34,183
  • 8
  • 77
  • 85
0

You don't have an instance of the derived class to initialize - you only have an instance of the base class. All the 1static_cast1 is doing is forcing the compiler to allow you to treat the base class as a derived class.

Instead, to create a B, you should be doing is this:

A* a = new B;

That will call the constructor of B, initializing m_b to 0.0.

JoeG
  • 12,994
  • 1
  • 38
  • 63
  • I realize that this is probably at the core of my problem. I should probably be instantiating a new B that calls the base class constructor – Hank May 11 '11 at 16:09
0
B* b = static_cast<B*>(a);

You should be using static_cast this only if you know that a actually points to an object of B or a class derived from B, which is clearly not the case.

It is an incorrect statement.
The valid sequence should be:

 A* a = new B();
 B* b = static_cast<B*>(a);

a now points to a object of the type B. It can do so because Pointer to the object of Base class can always point to the objects of the derived class, as long as it is a public derivation.

Now, you can use static_cast because you know for sure that a actually points to object of class B.
There can be scenarios where in one is not aware of the hierarchy of classes and in such scenarios one cannot use static_cast C++ provides another cast type called Dynamic_cast in such scenarios, it will return a null pointer if the cast is not valid in case of pointers or throw an exception in case of references.

Point to note though Dynamic_Cast works only with polymorphic classes.

Alok Save
  • 202,538
  • 53
  • 430
  • 533