1
votes

We know that, derived class members functions can be accessed through a base class pointer in C++ , provided that these member functions have to be virtual. Is there a means to access derived class member functions which are NOT virtual or pure virtual from base class pointer.

i.e. I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this?

For example, if I design a factory design pattern,

class Vehicle {
public:
    virtual void printVehicle() = 0;
    static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
    void printVehicle() {
        cout << "I am two wheeler" << endl;
    }
    void Some2WheelerONLYSpecificOPeration()
    {

    }
};
class ThreeWheeler : public Vehicle {
public:
    void printVehicle() {
        cout << "I am three wheeler" << endl;
    }
void Some3WheelerONLYSpecificOPeration()
    {

    }
};
class FourWheeler : public Vehicle {
    public:
    void printVehicle() {
        cout << "I am four wheeler" << endl;
    }
void Some4WheelerONLYSpecificOPeration()
    {

    }
};

// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
    if (type == VT_TwoWheeler)
        return new TwoWheeler();
    else if (type == VT_ThreeWheeler)
        return new ThreeWheeler();
    else if (type == VT_FourWheeler)
        return new FourWheeler();
    else return NULL;
}

int main()
{
Vehicle* basePtr =   Vehicle::Create(VT_TwoWheeler);
basePtr->Some2WheelerONLYSpecificOPeration();   //HOW TO ACHIEVE THIS CALL

basePtr =   Vehicle::Create(VT_ThreeWheeler);
basePtr->Some3WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL

basePtr =   Vehicle::Create(VT_FourWheeler);
basePtr->Some4WheelerONLYSpecificOPeration(); // //HOW TO ACHIEVE THIS CALL
}
3
dynamic_cast or visitor pattern.Jarod42
If they're not present in the base class, then you have to explicitly cast to the derived class.Oliver Charlesworth
Although the previous two answers tell you the mechanics of how to do such a thing, in most cases I feel the real answer is: don't do such a thing! It shows a failure to properly separate implementation and interface. Considering changing your design: either expand the interface of the base class, or do something else entirely (hard to say what without understanding context). Having derived-only interface is fine but you shouldn't need to access it from code that is interacting via the base class.Nir Friedman
@codeLover Can you specify your use case more please. What you want to do indicates you have a serious design flaw.user0042
You can do that, but only once before getting fired.n. 1.8e9-where's-my-share m.

3 Answers

1
votes

I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this ?

You cannot call a non-virtual member function of the derived class with a pointer to the base class.

You'll need a pointer to the derived class. The simplest method is to use dynamic_cast to get a pointer to the derived class, check whether the cast was successful, then call the derived class member function using a derived class pointer.

A better method would be to provide a virtual member function in the base class and implement it in the derived class.

1
votes

You can do what you want with dynamic_cast, but this will lead to disappointing results at a code review. Instead, I pitch you go the same route you did with printVehicle

class Vehicle
{
public:
    // without a virtual destructor you are walking into
    // a very bad bug. The wrong destructor may be called.
    virtual ~Vehicle()
    {
    } 
    virtual void printVehicle() = 0;

    // Specific stuff that all children must provide
    virtual void doTypeSpecificStuff() = 0;

    // this is actually a bit of a ideological weird. I'm not sure I can call
    // it a flaw. By making this factory function a member of Vehicle, Vehicle
    // must now know its children. If this is the case, the VehicleType enum
    // should probably be a member of Vehicle, but personally I think this
    // factory should be a totally free function.
    static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
    void printVehicle()
    {
        cout << "I am two wheeler" << endl;
    }
    void doTypeSpecificStuff()
    {
        cout << "Doing two wheeler stuff" << endl;
    }
};

Leaving out the other two classes and Vehicle::Create to save space.

int main()
{
    Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
    basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
    // leaking memory here, so
    delete basePtr;
    // but also look into std::unique_ptr. Much better suited to this behaviour


}

In fact, let's act on on that final comment about std::unique_ptr right now. A unique_ptr manages your dynamic allocations for you so you don't have to clutter up your code with deletes and run the risk of missing one or deleteing too soon. The unique_ptr's pointer is valid for as long as the unique_ptr is in scope. If you can compile, the pointer is good unless you done something silly like never point it at anything or manually remove the pointer.

And while we're at it, let's eliminate my earlier concerns about vehicle::Create.

First we define a free function to replace Create and return a unique_ptr. Since I hate to have to have if (ptr != NULL) checks all through my code to make sure an object really was created, let's also make a big stink about it when we can't match the provided vehicle type with class by throwing an exception.

And rather than a chain of if-else ifs we'll use a somewhat more elegant switch statement.

std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
    switch (type)
    {
        case  VT_TwoWheeler:
            return std::make_unique<TwoWheeler>();
        case  VT_ThreeWheeler:
            return std::make_unique<ThreeWheeler>();
        case  VT_FourWheeler:
            return std::make_unique<FourWheeler>();
        default:
            throw std::runtime_error("Invalid Vehicle type");
    }
}    

And then we'll use this new function

int main()
{
    try
    {
        std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
        basePtr->doTypeSpecificStuff();

        basePtr = SmarterVehicleFactory(VT_ThreeWheeler); 
        // unique_ptr freed the TwoWheeler for us.
        basePtr->doTypeSpecificStuff(); 

        basePtr = SmarterVehicleFactory(VT_FourWheeler);
        basePtr->doTypeSpecificStuff(); 

        // just for laughs we will ask for a FiveWheeler, which we have not yet 
        // fully implemented
        basePtr = SmarterVehicleFactory(VT_FiveWheeler);  // will throw exception
        basePtr->doTypeSpecificStuff(); // will not be executed
    }
    catch (const std::exception & exc)
    {
        cerr << "Rats! Something bad happened: " << exc.what();
        // basePtr will be unmodified and still pointing to a FourWheeler
    }
} // basePtr  will go out of scope here and clean up our memory for us.

The beauty of this approach is no class knows anything about any other class. You can put Vehicle in a header with the SmarterVehicleFactory prototype and the list of vehicle types and hide everything else. The user sees nothing. Everybody is kept in the dark.

Why is that good? Because now you can change any of the above classes, except the Vehicle interface class, without having any effect on any of the other classes. This makes your code easier to maintain and debug.

0
votes

I'm trying to find the best way to use polymorphism without using inheritance, because I want to avoid virtual calls. I was looking for a way to improve what I currently have (with no avail) and I stumbled on this question. This is the best I can do so far:

template<class VehicleDetails>
class Vehicle {
    VehicleDetails details;

public:
    VehicleDetails& getDetails() {
        return details;
    }

    const VehicleDetails& getDetails() const {
        return details;
    }

    void printDetails() const {
        details.printDetails();
    }
}

class TwoWheeler {
public:
    void printDetails() const {
        cout << "I am two wheeler" << endl;
    }

    void specificTwoWheelerMethod() const {
        cout << "I am specific functionality" << endl;
    }
}

Then you use it as such:

Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"

Unfortunately this complicates things. Now every class/struct or function that takes a vehicle must be templated, unless you know the type of vehicle.

template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
    // ...
}

On the plus side when you do know the type you can access specific functionality via the getDetails() method without any casting or runtime overhead involved:

void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
    twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}