views:

107

answers:

5

I have few problems with my basic and would be thankful if someone can clear this.

1: What does it mean when I say base *b = new derived; Why would one go for this? We very well separately can create objects for class base and class derived and then call the functions accordingly. I know that this base *b = new derived; is called as Object Slicing but why and when would one go for this?

2: I know why it is not advisable to convert the base class object to derived class object (because base class is not aware of the derived class members and methods). I even read in other StackOverflow threads that if this is gonna be the case then we have to change/re-visit our design. I understand all that, however, I am just curious, Is there any way to do this?

    class base
    {
    public:
        void f(){cout << "In Base";}
    };

    class derived:public base
    {
    public:
        void f(){cout << "In Derived";}
    };

    int _tmain(int argc, _TCHAR* argv[])
    {
        base b1, b2;
        derived d1, d2;
        b2 = d1;
        d2 = reinterpret_cast<derived*>(b1); //gives error C2440
        b1.f(); // Prints In Base
        d1.f(); // Prints In Derived
        b2.f(); // Prints In Base
        d1.base::f(); //Prints In Base
        d2.f();
        getch();
        return 0;
    }

3: In case of my above example, is there any way I could call the base class f() using derived class object? I used d1.base()::f() I just want to know if there any way without using scope resolution operator?

Thanks a lot for your time in helping me out!

A: 

Yes and no. You can go class derived: public base { public: void f() { base::f(); } };

I'm not too sure about at a global scope though.

Duracell
A: 

Question 1: Why would you do this: you probably wouldn't do this directly. The case where this would happen would be where you had, for example, a function that returns "some kind of base*" and you don't care which type.

Question2: from within derived, you need to use the scope resolution operator to specify that you want to use the base class' implementation.

Note: you have not declared your function virtual, so you are not actually going to get the behavior you are expecting.

jwismar
A: 
base *b = new derived

Creating Base class pointer that points to derived class object. This allows you to create is-a relationship. Class Derived is a Base. Please refer inhertance for more details.

2. d2 = reinterpret_cast<derived*>(b1); You are trying to convert a base class object to derived class object. But the cast operation used is . Its not correct.

If you are planning to call base class method then use Base class pointers.

Base* ptr = &b1;
ptr->f();

I recommend you to refer FAQ Lite.

aJ
+5  A: 

1. This is not object slicing:

base *b = new derived;

This is assigning a pointer of type base to an instance of derived.

One (very common) example of this in action is in callbacks. Consider this:

class Observer
{
public:
    virtual void OnEvent() = 0;
};

class Subject
{
public:
    Subject() : observer(0) {}
    void SetObserver(Observer* o) { observer = o; }
    void FireEvent() { if(observer != 0) observer->OnEvent(); }
private:
    Observer* observer;
};

class MyObserver : public Observer
{
public:
    void OnEvent() { ::printf("Hi there!\n"); }
};

int main()
{
    Subject s;
    MyObserver o;
    s.SetObserver(&o);
    s.FireEvent();
    return 0;
}

This should be the expected output:

Hi there!

Notice what is happening here. We're passing in a pointer to an instance of MyObserver to SetObserver() even though the function only accepts pointers of type Observer. This works because MyObserver (publicly) derives from Observer. In this case, we say that MyObserver is-an Observer.

The Observer type defines a pure virtual function (The =0 means that the function is pure; it must be implemented by derived classes). The virtual keyword tells the compiler that calling the function should cause the most-derived function to be executed. The OnEvent() function in MyObserver is the most-derived, therefore, that version is called, even though we are calling OnEvent() on a pointer of type Observer.

We go through the trouble of doing all this because in this code Subject doesn't have to know the exact type of its observer - the observers just have to derive from Observer and the Subject instance will call the most derived type's implementation of OnEvent(). This allows for code decoupling - Subject doesn't depend on MyObserver, and MyObserver doesn't depend on Subject.

2. There's nothing wrong with casting a pointer from a base to derived type per se. The following is in fact legal and guaranteed to work:

class Base {};
class Derived : public Base {};

int main()
{
    Derived d;
    Base* bp = &d;
    Derived* dp = static_cast<Derived*>(bp);
    return 0;
}

The line before the return statement in this snippet, however, is undefined:

class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};

int main()
{
    Derived1 d1;
    Base* bp = &d1;
    Derived2* d2p = static_cast<Derived2*>(bp); // WTF?!
    return 0;
}

The value of the d2p pointer is meaningless, and attempting to access anything in it will certainly cause a crash, because the bp pointer doesn't actually point to a Derived2 instance, it points to a Derived1 instance. Compilers cannot catch this at compile time, because both Derived1 and Derived2 inherit from Base, so the cast successfully compiles. This is the main danger with casting from a base to a derived type - you won't know until runtime if the cast actually returns meaningful results.

Of course, unless you use dynamic_cast<>(), but the cast incurs a runtime penalty. static_cast<>() involves at most, pointer arithmetic. reinterpret_cast<>() forces a pointer to take on a different (potentially unrelated) type, without performing any pointer arithmetic. This makes reinterpret_cast<>() one of the more dangerous casts and should be used only when necessary, especially if static_cast<>() can do the job.

3. Consider the following:

class Base
{
public:
    void Foobar() { ::printf("In Base!\n"); }
};

class Derived : public Base
{
public:
    void Foobar() { ::printf("In Derived!\n"); }
};

int main()
{
    Derived d;
    Derived* dp = &d;
    Base* bp = dp;
    dp->Foobar();
    bp->Foobar();
    return 0;
}

If the Foobar() function is not virtual, then you will get this output:

In Derived!
In Base!

Otherwise, if the Foobar() function is virtual, then you will get this output:

In Derived!
In Derived!

To guarantee that a call to the virtual function Foobar() invokes the base implementation via the base pointer, then you have to use the scope resolution operator:

// Prints "In Base!", even if bp actually points
// to an instance of Derived overriding Foobar().
bp->Base::Foobar();
In silico
*"The `=0` means that the function is pure - it doesn't exist"* - not quite, it means that the deriving class has to implement it. It can still be implemented by the base as well, i.e. `virtual void f() = 0 {}` is fine.
Georg Fritzsche
Good call. I have edited that sentence. For those wondering why one might define a pure virtual function, see http://www.gotw.ca/gotw/031.htm
In silico
that info slapped me in the face :) I always thought that pure virtuals can't have body
grapkulec
Also, pure virtual destructors must have a body.
jwismar
A: 
jasonline