see comments. set me straight. many, many thanks...

3 questions about inheritance, pointers, & polymorphism

#include <iostream>
using namespace std;

class baseClass {
  public:
    void nVirt() {
        cout << "not virtual, base " << endl;
    }
    virtual void yVirt() {
        cout << "virtual, base " << endl;
    }
};

class derivedClass : public baseClass {
  public:
    void nVirt() {
        cout << "not virtual, derived " << endl;
    }
    virtual void yVirt() {
        cout << "virtual, derived " << endl;
    }
};

int main()
{
    baseClass someBase;         //base obj
    baseClass * basePtr;        //base obj pointer
    derivedClass someDerived;   //derived obj
    derivedClass * derivedPtr;  //derived obj pointer

    basePtr = &someBase;        //set base obj pointer to base obj
    basePtr->nVirt();           //as expected
    basePtr->yVirt();           //as expected

    basePtr = &someDerived;     //set bas obj pointer to derived obj
    basePtr->nVirt();           //????
/*
why does a pointer of base type still call base methods when it is
pointing to the address of a derived obj? do base obj pointers
always point to base methods even when pointing to derived obj's?
*/
    basePtr->yVirt();           //????
/*
why should i be surprised that same pointer is calling the yvirt
function since it is pointing to a derived object? shouldn't a
pointer to a derived object also point to that object's members?
*/
    derivedPtr = &someBase;     //ERROR????
/*
i've read that a pointer to derived obj can point to a
base obj. why not here? what gives?
*/
    return 0;
}

Recommended Answers

All 4 Replies

Ok, so:

#1 - What you're experiencing is due to something called early (static) binding. At run time, your compiled code has no clue about basePtr pointing to derivedObject. This is one reason you use virtual functions. If you noticed, your last function call did actually call the derived function ("virtual, derived" was output). This demonstrates the differences between early and late binding.

#2 - Same answer as before. The only reason you're calling yVirt() is because it is in fact a virtual function. Virtual functions are not bound at compile time, but instead are bound during run time. This way, your program can decide during run time which function needs to be called based on which object is calling the function.

#3 - Technically possible, but you'll get a load of exceptions. Newer compilers probably won't even compile that.

A very good resource that should help you better understand these topics.

basePtr->nVirt(); //????
/*
why does a pointer of base type still call base methods when it is
pointing to the address of a derived obj? do base obj pointers
always point to base methods even when pointing to derived obj's?
*/

Because even though it's a derived object, there is a base object that exists within it that it's actually pointing to. Since the method isn't virtual, it uses an "early binding" and doesn't redirect the call to the derived object's version of the method.

basePtr->yVirt(); //????
/*
why should i be surprised that same pointer is calling the yvirt
function since it is pointing to a derived object? shouldn't a
pointer to a derived object also point to that object's members?
*/

As Duki mentioned, this is the result of "late binding". This causes an external call to yVirt() to automatically redirect to the derived version because it's 1.) actually a derivedClass object being pointed and 2.) the method is declared virtual. To access the base version, you would call basePtr->baseClass::yVirt()

derivedPtr = &someBase; //ERROR????
/*
i've read that a pointer to derived obj can point to a
base obj. why not here? what gives?
*/

It can't without some trickery because a base object is not a derived object. Whereas a derived object is a base object. In general, inheritance is a heavily policed one-way street.

Perhaps an analogy will help:
It's similar to the Chevrolet Corvette. The second and third generation Corvettes (from 1963 to 1982, known as "C2"s and "C3"s), were called "Stingrays", but C1, C4, C5, and C6 models are not. This requires that a distinction be made. A Stingray is a Corvette, but not all Corvettes are Stingrays.

>> #3 - Technically possible, but you'll get a load of exceptions. Newer compilers probably won't even compile that.

that is where the `reinterpret_cast<>` exists.The safe way around this is
the `dynamic_cast<>'.And the exception is `std::bad_cast` exception.But I never
heard that newer compiler does not support it anywhere , yes sources please.

My source is compiling his code for myself and getting errors on that line in Visual Studio 2010...

error C2440: '=' : cannot convert from 'main::baseClass *' to main::derivedClass *'

Keep in mind that I'm referring to o/p code - not the casting you mention.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.