C++ inheritance - subclasses constructor call?

700 Views Asked by At

I have the following in the main:

Sum *sum = new Sum(Identifier("aNum1"), Identifier("aNum2"));

And my classes are:

class Table {
private:
    static map<string, int> m;    
public:
    static int lookup(string ident)
    {
        return m.find(ident)->second;
    }
    static void insert(string ident, int aValue)
    {
        m.insert(pair<string, int>(ident, aValue));
    }
};   

class Expression {
public:
    virtual int const getValue() = 0;
};

class Identifier : Expression {
private:
    string ident;
public:
    Identifier(string _ident) { ident = _ident; }
    int const getValue() { return Table::lookup(ident); }    
};

class BinaryExpression : public Expression {
protected:
    Expression *firstExp;
    Expression *secondExp;
public:
    BinaryExpression(Expression &_firstExp, Expression &_secondExp) {
        firstExp = &_firstExp;
        secondExp = &_secondExp;
    }
};

class Sum : BinaryExpression {
public:
    Sum(Expression &first, Expression &second) : BinaryExpression (first, second) {}
    int const getValue() 
    { 
        return firstExp->getValue() + secondExp->getValue();
    }
};

When I am compiling it I get the following error:

no matching function for call to 'Sum::Sum(Identifier, Identifier)'

candidates are: Sum::Sum(Expression&, Expression&)

The Identifier class is inheriting from Expression, so why am I getting this error?

5

There are 5 best solutions below

0
On
class Identifier : Expression {
private:
    string ident;
public:
    Identifier(string _ident) { ident = _ident; }
    int const getValue() { return Table::lookup(ident); }    
};

You are privately inheriting Identifier from Expression change to:

class Identifier : public Expression {
private:
    string ident;
public:
    Identifier(string _ident) { ident = _ident; }
    int const getValue() { return Table::lookup(ident); }    
};
2
On

The inheritance does not matters. You should pass the instances of Expression instead of Identifier.

Sum *sum = new Sum(Expression("aNum1"), Expression("aNum2"));
1
On

The problem is that you are passing temporaries to your constructor but the constructor expects a non-const reference, while temporaries can only bind to const references.

To fix it, change the parameter type to Expression const&. This, by the way, is completely unrelated to inheritance and polymorphism (but digivampire’s fix is also needed; I’m suspecting that was just a typo).

0
On

You need Sum(Expression const & first, Expression const & second).

Without the consts it won't compile - non-const references won't bind to a temporary, like your temporary Identifier objects.

But even then it won't work - you'll end up with dangling pointers to the Identifiers. You might be better of with something like:

new Sum(new Identifier("aNum1"), new Identifier("aNum2"));

But then you need to work out how to free things at the right time.

0
On

As I understand it, down-casting (which is what you're trying to achieve) is not automatic and you should force it.

However, to cast Identifier to Expression you need the pointer to those objects. Thus, if you want to keep your Sum class constructor the way it is, you need to call it like this:

Identifier a("aNum1");
Identifier b("aNum2");
Sum *sum = new Sum(*(Expression*) &a, *(Expression*) &b);