Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

call a childs version of a function instead of a parents?

Okay, so I got two classes.

class a{
public:
a(){};
void print(){cout << "hello"};
}

class b : public a{
public:
void print(){cout << "hello world";}
}

And a array of parents with a child

a blah[10];
blah[5] = b();

Than I call print, and want it to say hello world.

blah[5].print();

But it calls the parent. How do I fix this?

like image 837
CyanPrime Avatar asked Apr 13 '11 04:04

CyanPrime


2 Answers

This can be fixed by declaring the function virtual, a la:

class a{
public:
    virtual void print(){
        cout << "hello";
    }
}

class b : public a{
public:
    virtual void print() {
        cout << "hello world";
    }
}

This is how one implements polymorphism in C++. More here: http://en.wikipedia.org/wiki/Virtual_function

However, it should be noted that in your example, it will never call the child function, because you are using object values, not pointers/references to objects. To remedy this,

a * blah[10];
blah[5] = new b();

Then:

blah[5]->print();
like image 169
Roadrunner-EX Avatar answered Oct 26 '22 13:10

Roadrunner-EX


What you're looking for is run-time polymorphism, which means to have the object take "many forms" (i.e. a or b), and act accordingly, as the program runs. In C++, you do this by making the function virtual in the base class a:

virtual void print() {cout << "hello"}; 

Then, you need to store the elements by pointer or reference, and - as in general the derived classes can introduce new data members and need more storage - it's normal to create the objects on the heap with new:

a* blah[10];
blah[5] = new b();

Then you can call:

blah[5]->print();  

And it will call the b implementation of print().

You should later delete blah[5] (and any other's you've pointed at memory returned by new).

In practice, it's a good idea to use a container that can delete the objects it contains when it is itself destructed, whether due to leaving scope or being deleted. std::vector<> is one such container. You can also use smart-pointers to automate the deletion of the a and b objects. This helps make the code correct if exceptions are thrown before your delete statements execute, and you want your program to keep running without leaking memory. The boost library is the easiest/best place to get a smart pointer implementation from. Together:

#include <vector>
#include <boost/shared_ptr.hpp>

std::vector<boost::shared_pointer<a> > blah(10);

blah[5] = new b();

(It's more normal to use vectors with push_back(), as it automatically grows the vector to fit in all the elements you've added, with the new total available by calling vector::size().)

like image 21
Tony Delroy Avatar answered Oct 26 '22 14:10

Tony Delroy