0

I've looked around at multiple questions on this topic on SO as well as several references and have not seen this issue come up anywhere.

When my instance of Derived calls Base::GetValue() (which calls the virtual doGetValue(), defined in Derived and in Base), Base::doGetValue() is called instead of Derived::doGetValue(). Why is that and what do I need to do differently?

Is it because Derived::doGetValue() is private instead of protected? That seems to me to be the most likely explanation, but I haven't seen that explicitly stated anywhere that I've looked so far.

Here is my code on coliru.

Below is my code:

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <memory>

using namespace std;

class Base
{
private:
    virtual string      doGetname(  ) const { return "Base"; };

protected:
    virtual void        doGetValue( map<string,string> &ds, const bool include ) const;
    inline void         doGetValue( map<string,string> &ds ) const { doGetValue(ds, true); };

public:
    string              GetValue(  ) const;
    string              GetName(  ) const { return doGetname(); };
};

class Derived : public Base
{
private:
    virtual void        doGetValue( map<string,string> &ds ) const;
    virtual string      doGetname(  ) const { return "Derived"; };
};

struct generate_value_from_map : std::unary_function<void, void>
{
    generate_value_from_map( string *_val, const string assignment = "  " ):val(_val)
    {
        count = 0;
        insert = (*_val);
        first = "(";
        second = ") "+assignment+" (";
    }
    void operator() (pair<const string,string> &i)
    {
        first += ( count > 0 ? "," : "" ) + i.first;
        second += ( count > 0 ? "," : "" ) + i.second;

        (*val) = insert + first + second + ")";

        ++count;
    }

private:
    int count;
    string *val;
    string insert;
    string first;
    string second;
};

string  Base::GetValue(  ) const
{
    string ret_val = "name is: " + GetName() + " \n";
    map<string,string> ret_map;
    this->doGetValue(ret_map);
    for_each(ret_map.begin(), ret_map.end(), generate_value_from_map(&ret_val));
    return ret_val;
}

void  Base::doGetValue( map<string,string> &ds, const bool include ) const
{
    //base implementation
    //fills ds with values from Base
    ds["type"] = "Base";
    ds["id"] = "Id";
}

void  Derived::doGetValue( map<string,string> &ds ) const
{
    Base::doGetValue( ds );
    //derived implementation
    //fills ds with values from Derived
    ds["type"] = "Derived";
    ds["name"] = "Name";
}

int main()
{
    shared_ptr<Derived> obj ( new Derived() );

    string val = obj->GetValue();

    cout << val;

    //do stuff with val
}

I tried to include all the specifics of my issue, excluding some of the delphi-inherited features of my compiler (RAD Studio XE4).

1 Answer 1

2

The definitions of doGetValue are different between base and derived.

Base:

virtual void        doGetValue( map<string,string> &ds, const bool include ) const;
inline void         doGetValue( map<string,string> &ds ) const { doGetValue(ds, true); };

Derived:

virtual void        doGetValue( map<string,string> &ds ) const;

In the base the function is not virtual.

Sign up to request clarification or add additional context in comments.

3 Comments

So I need the overloaded doGetValue(...) to be virtual inline instead of just inline?
Inline is meaningless in virtual functions. you can drop it. it must be virtual in your example.
Thanks, that takes care of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.