C ++继承 - 子类构造函数调用?

时间:2011-11-02 12:52:51

标签: c++ inheritance constructor object-slicing

我在主要内容中有以下内容:

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(Expression&amp;,Expression&amp;)

Identifier类继承自Expression,为什么我会收到此错误?

5 个答案:

答案 0 :(得分:7)

问题在于您将临时值传递给构造函数,但构造函数需要 - const引用,而temporaries只能绑定到const引用。

要解决此问题,请将参数类型更改为Expression const&。顺便说一下,这与继承和多态完全无关(但也需要digivampire的修复;我怀疑这只是一个错字)。

答案 1 :(得分:4)

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

答案 2 :(得分:0)

您需要Sum(Expression const & first, Expression const & second)

如果没有const s它将无法编译 - 非const引用将不会绑定到临时引用,如临时Identifier对象。

但是即使这样它也行不通 - 你最终会指向标识符的悬空指针。你可能会更喜欢这样的事情:

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

但是你需要弄清楚如何在正确的时间解放东西。

答案 3 :(得分:-1)

据我所知,向下投射(这是你想要实现的)不是自动的,你应该强迫它。

但是,要将Identifier转换为Expression,您需要指向这些对象的指针。因此,如果你想保持你的Sum类构造函数的方式,你需要像这样调用它:

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

答案 4 :(得分:-3)

继承并不重要。您应该传递Expression的实例而不是Identifier。

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