C ++ наследование - вызов конструктора подклассов? - PullRequest
2 голосов
/ 02 ноября 2011

У меня в основном следующее:

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

И мои занятия:

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();
    }
};

Когда я его компилирую, я получаю следующую ошибку:

нет соответствующей функции для вызова 'Sum :: Sum (Identifier, Identifier)'

Кандидатами являются: Sum :: Sum (Выражение &, Выражение &)

Класс Identifier наследуется от Expression, так почему я получаю эту ошибку?

Ответы [ 5 ]

7 голосов
/ 02 ноября 2011

Проблема в том, что вы передаете временные данные в свой конструктор, но конструктор ожидает ссылку non - const, тогда как временные ссылки могут связываться только с const ссылками.

исправить это, изменить тип параметра на Expression const&.Это, кстати, совершенно не связано с наследованием и полиморфизмом (но исправление дигивампира также необходимо; я подозреваю, что это была просто опечатка).

4 голосов
/ 02 ноября 2011
class Identifier : Expression {
private:
    string ident;
public:
    Identifier(string _ident) { ident = _ident; }
    int const getValue() { return Table::lookup(ident); }    
};

Вы унаследовали Идентификатор из выражения в:

class Identifier : public Expression {
private:
    string ident;
public:
    Identifier(string _ident) { ident = _ident; }
    int const getValue() { return Table::lookup(ident); }    
};
0 голосов
/ 02 ноября 2011

Насколько я понимаю, понижение (а это то, что вы пытаетесь достичь) не является автоматическим, и вы должны его форсировать.

Однако для приведения идентификатора в выражение вам необходим указатель на эти объекты.Таким образом, если вы хотите сохранить конструктор класса Sum таким, какой он есть, вам нужно назвать его так:

Identifier a("aNum1");
Identifier b("aNum2");
Sum *sum = new Sum(*(Expression*) &a, *(Expression*) &b);
0 голосов
/ 02 ноября 2011

Вам нужно Sum(Expression const & first, Expression const & second).

Без const s он не скомпилируется - неконстантные ссылки не будут привязываться к временным, как ваши временные Identifier объекты.

Но даже тогда это не сработает - в итоге вы получите висячие указатели на идентификаторы.Вам может быть лучше с чем-то вроде:

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

Но тогда вам нужно решить, как освободить вещи в нужное время.

0 голосов
/ 02 ноября 2011

Наследство не имеет значения.Вы должны передать экземпляры Expression вместо Identifier.

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