Deni J
Deni J

Reputation: 19

Parent class using method from child

Is there a way I can use child methods with a parent class pointer:

#include <iostream>
class Parent {
public:

    int a;

    virtual int ret() {
        return a;
    }
};

class Child: public Parent {
    int b;

public:
    int ret() {
        return a;
    }

    int retB() {
        return b;
    }
};

void main() {
    Parent* parent = new Child();

    parent->retB();
}

Im using an array of Parent pointers with derived classes as members. Is there a simple solution to this or should i just rethink my code?

Upvotes: 1

Views: 180

Answers (1)

Fureeish
Fureeish

Reputation: 13424

Out of the blue? No.

With certain checks? Yes.

What do I mean by that? Suppose you have a following class hierarchy:

struct Base {};
struct DerOne : Base {};
struct DerTwo : Base {};

Then you create a pointer of Base type to some derived class:

Base* b_ptr = new DerTwo();

It compiles correctly. Now imagine you want to call DerTwo's imaginary method. In your world, it may be ok, but why it's not?

There would have to be some checks, whether or not what b_ptr points to actually implements the method you want to invoke. These checks are not automatically performed. In C++ you don't pay for what you don't need. It'd be pointless to have those kind of checks every time we call any method via a pointer.

So how can you achieve it?

You have to ensure that b_ptr points to something that implements the method you want to invoke. How?

static_cast vs dynamic_cast:

Base class' pointer cannot invoke methods that are not declared in Base class. That's a fact. Done. If you wish to invoke some method from Derived class, you need to change the type of the pointer. How you do that? You either use static_cast<> or dynamic_cast<>. Here you can read more about C++ casts, but for now, I will tl;dr this question and answer for your specific example.

Option #1: You know that type pointed to by b_ptr is of a certain class (let's assume we're talking about DerTwo) and you want to invoke a foo() method declared inside it.

You use static_cast<>. You use it because you know and are certain that there is a specific, derived type object pointed to by a base class pointer. Regarding our example, it'd look like this:

Base* b_ptr = new DerTwo();
DerTwo* der_ptr = static_cast<DerTwo*>(b_ptr);

der_ptr->foo(); // b_ptr and der_ptr point to the same object

Option #2: You don't know the type of the object pointed by b_ptr and want to check if it's safe to call foo().

Suppose that foo() is declared only in DerTwo. Thus, if b_ptr points to DerOne object and you'd want to call foo(), terrible things would happen. You'd call a non-existing method. You have to perform a check, via dynamic_cast<>:

Base* b_ptr = new DerTwo();
DerTwo* der_ptr = dynamic_cast<DerTwo*>(b_ptr);

if(der_ptr != nullptr){
    der_ptr->foo(); // b_ptr and der_ptr again point to the same object
} else {
    // b_ptr somehow does NOT point to DerTwo object
}

dynamic_cast<> performs a check, whether or not it's argument actually points to the object of specified type. It it does, it returns a pointer of the specified type to the object. If it fails, it returns nullptr, so all you have to do to check if your dynamic casting succeeded, is compare it's result to nullptr.

Upvotes: 2

Related Questions