重写方法调用时的C ++奇怪异常

时间:2014-12-20 12:19:38

标签: c++ function methods

我有一个基类A,它永远不会被实例化:

class A {
public:
    virtual void visit(Visitor * v) { }
};

Visitor也只是一个基类,它也永远不会被实例化:

class Visitor {
public:
    virtual void visit(A * a) { }

    virtual void visit(B * b) { }
    virtual void visit(C * c) { }
    virtual void visit(D * d) { }
};

以下是B,C和D类:

class B : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};

class C : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};

class D : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};

现在我继承了访客:

class FooVisitor : public Visitor {
public:
    virtual void visit(A * a) { a->visit(this); }

    virtual void visit(B * b) { /*do something*/ }
    virtual void visit(C * c) { /*do something*/ }
    virtual void visit(D * d) { /*do something*/ }
};

最后我做了主要的:

int main() {
    A * something = getSomethingLikeA(); // Returns a pointer to a B, C or D instance
    FooVisitor * v = new FooVisitor();
    v->visit(something);
    return 0;
}

我在访问方法调用时得到一个未处理的异常。更具体地说,这是我的情况视频:LINK

我不知道是什么导致它,调试器并没有真正帮助我。

编辑: 以下是实际程序的来源:download(8.31 KiB)

2 个答案:

答案 0 :(得分:0)

您创建的层次结构和正在使用的设计会在大多数情况下导致无限递归调用。我相信这是例外的原因。

    A * something = getSomethingLikeA();   
//Let's say you get object of type B.

    v->visit(something);
///would call FooVisitor's
    virtual void visit(A * a) { a->visit(this); }
//then class B's
    virtual void visit(Visitor * v) { v->visit(this); }
//and then again Foovisitor's
    virtual void visit(A * a) { a->visit(this); }  ////huh? I just called it back 
                                                   ////few stack frames.

疲惫不堪之后,除了直接抛出异常以摆脱这些特点外别无他法......

答案 1 :(得分:0)

通过查看代码,您可以看到parseXYZ类的某些Parser成员函数在所有代码路径中都缺少return语句,这是的途径您遇到的未定义行为

Exp * parseRelExp() {
    Exp * left = parseBinaryExp();
    if (lookahead->type == EQUALS || lookahead->type == NOT_EQUALS || lookahead->type == GREATER_THAN || lookahead->type == LESS_THAN || lookahead->type == GOE_THAN || lookahead->type == LOE_THAN) {
        TokenType op = lookahead->type;
        next();
        Exp * right = parseExp();
        if (right != nullptr) {
            return new RelExp(left, op, right);
        }
        else expect("Expression");
    }
    // what if we get here??
}

在大多数情况下(虽然它仍然未定义),返回的值是来自堆栈的任意垃圾,当被解释为指针时,可能会在解除引用时导致应用程序崩溃。