Start New Discussion within our Software Development Community

How come the output of this program is 1413, I expected it to be 1414.
(i + 1)->value() should have called R::value(). is n't it?

#include<iostream>
#include<vector>
using namespace std;

class Q
{
public:
    Q(int n = 0) : m_n(n) { }
    virtual int value() const { return m_n; }
    virtual ~Q() { }
protected:
    int m_n;
};

class R : public Q
{
public:
    R(int n = 0) : Q(n) { }
    virtual int value() const { return m_n + 1; }
};
int main(void)
{
    const Q a(1);
    const R b(3);
    const Q *x[2] = { &a, &b };
    typedef std::vector<Q> V;
    V y;
    y.push_back(a);
    y.push_back(b);
    V::const_iterator i = y.begin();
    std::cout << x[0]->value() << x[1]->value()
              << i->value() << (i + 1)->value() << std::endl;
}

Indeed, but, defining your vector as a Q class, will interpret all its objects inside of him as being of type Q, thus, when pushing back a and b, you are pushing back copies of those object, copies which will be interpret as being of Q class, and since a takes 1 in the constructor, and b takes 3 in the constructor, that will actually be their output (will call the Q function value, which will return the exact value). But, if you change your vector declaration so that it would hold pointers to objects of type Q, you will actually store pointers to the real objects (not copies of them), which will be interpret as they are.

So, changing

typedef std::vector<Q> V;

to

typedef std::vector<const Q*> V ;

and

y.push_back(a);
y.push_back(b);

to

y.push_back(&a);
y.push_back(&b);

will solve your problem.

For a deeper understanding of the situation, put a cout in every value function from both Q and R, like

virtual int value() const { cout<<"Qvalue\n"; return m_n; }
virtual int value() const { cout<<"Rvalue\n"; return m_n + 1; }

and see what function is actually been called.

This article has been dead for over six months. Start a new discussion instead.