virtual function question

Question!
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>

class Helper 
{
public:
    Helper() { init(); }
    virtual void print() {
        int nSize = m_vItems.size();
        std::cout << "Size : " << nSize << std::endl;
        std::cout << "Items: " << std::endl;
        for(int i=0; i<nSize; i++) {
            std::cout << m_vItems[i] << std::endl;
        }
    }
protected:
    virtual void init() { m_vItems.push_back("A"); }
    std::vector<std::string> m_vItems;
};

class ItemsHelper : public Helper
{
public:
    ItemsHelper() { }
protected:
    virtual void init() { 
        Helper::init();
        m_vItems.push_back("B");
    }
};

int _tmain(int argc, _TCHAR* argv[]) {
    ItemsHelper h;
    h.print();
}

This output's that the size of the vector is 1. I expected the size to be 2 because in the ItemsHelper::init function I called the base class Helper::init() function, then I add a second item to the vector. The problem is, the ItemsHelper::init doesn't get called, the base class init function gets called instead.

I want the ItemsHelper::init function to get called, and I can do that by calling the init function in the ItemsHelper ctor rather than in the base class. BUT, the question is, is there a better way to achieve that and still keep the call to the init() in the base class? Because what if I want to create a Helper object instead of a ItemsHelper, then the init function would never get called.

btw, this is a simplified version of a issue I'm seeing in a much larger object, I just made these objects up for example.

By : cchampion


Answers

The problem is that virtual functions don't work the way you think they do in constructors. When an ItemsHelper is constructed, first the base class Helper in constructed. In its constructor, the type of the object is Helper, so the call to init calls Helper::init(). Then the ItemsHelper constructor is called. There is no way to call a derived class function from a base class constructor. The best you can do is call init() after the ItemsHelper object is constructed.

By : KeithB


This video can help you solving your question :)
By: admin