2017-05-01 11 views
1

私は、解析ツリーのXML出力を生成するVisitorクラスをC++で実装しています。未定義 'クラスのvtable'への参照

Windows上でClionでコンパイルすると、コードがコンパイルされますが、期待される結果が出力された後に実行されるとクラッシュします。エラーコードは、この

プロセスは、私は(Clionなし)のgccを使用してコンパイルしようとすると、私はエラーメッセージ

は未定義取得終了コード-1073741819(0xc0000005)に

を終了しました'PrintXMLVisitorのためのvtable'への参照。

私のコードは次のとおりです。私はASTTypeNode.cppにエラー

ASTNode.h

#ifndef MINILANG_ASTNODE_H 
#define MINILANG_ASTNODE_H 

#include <memory> 
class Visitor; 

class ASTNode { 
public: 
    virtual void accept(std::shared_ptr<Visitor> visitor) = 0; 
}; 


#endif //MINILANG_ASTNODE_H 

ASTTypeNode.h

#ifndef MINILANG_ASTTYPENODE_H 
#define MINILANG_ASTTYPENODE_H 


#include "ASTNode.h" 

class ASTTypeNode: public ASTNode { 
public: 
    enum Type {Real, Int, Bool, String}; 
    ASTTypeNode(Type type); 
    Type getType() const; 

    void accept(std::shared_ptr<Visitor> visitor) override; 

private: 
    Type type; 
}; 


#endif //MINILANG_ASTTYPENODE_H 

を生成最低限に

#include "ASTTypeNode.h" 
#include "Visitor.h" 

ASTTypeNode::ASTTypeNode(ASTTypeNode::Type type) 
    : type(type) 
{ 

} 

ASTTypeNode::Type ASTTypeNode::getType() const { 
    return type; 
} 

void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor) { 
    visitor->visit(std::shared_ptr<ASTTypeNode>(this)); 
} 
をそれを下に蒸留しています

Visitor.h

#ifndef MINILANG_VISITOR_H 
#define MINILANG_VISITOR_H 

#include <memory> 
#include "ASTTypeNode.h" 


class Visitor { 
public: 
    virtual void visit(std::shared_ptr<ASTTypeNode> typeNode) = 0; 
}; 


#endif //MINILANG_VISITOR_H 

PrintXMLVisitor.h

#ifndef MINILANG_PRINTXMLVISITOR_H 
#define MINILANG_PRINTXMLVISITOR_H 


#include "Visitor.h" 

class PrintXMLVisitor: public Visitor { 
public: 
    void visit(std::shared_ptr<ASTTypeNode> typeNode) override; 
}; 


#endif //MINILANG_PRINTXMLVISITOR_H 

PrintXMLVisitor.cpp

#include "PrintXMLVisitor.h" 
#include <iostream> 

void PrintXMLVisitor::visit(std::shared_ptr<ASTTypeNode> typeNode) { 

    std::string typeName; 
    switch(typeNode->getType()) 
    { 
     case ASTTypeNode::Type::Real: 
      typeName = "Real"; 
      break; 
     case ASTTypeNode::Type::Int: 
      typeName = "Int"; 
      break; 
     case ASTTypeNode::Type::Bool: 
      typeName = "Bool"; 
      break; 
     case ASTTypeNode::Type::String: 
      typeName = "String"; 
      break; 
     default: 
      typeName = "Error"; 
      exit(22); 
    } 

    std::cout << "<TypeNode>" << typeName << "</TypeNode>" << std:: endl; 
} 

main.cppに

#include <iostream> 
#include "Lexer.h" 
#include "ASTTypeNode.h" 
#include "PrintXMLVisitor.h" 

int main() { 

    ASTTypeNode astTypeNode (ASTTypeNode::Type::Int); 
    astTypeNode.accept(std::make_shared<PrintXMLVisitor>()); 


    return 0; 
} 
+0

ええ、私のせいで、ブラウザが間違っています。 – jiveturkey

答えて

-1

作成した共有ポインタが動的ではありません。具体的には、その文で

void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor) { 
    visitor->visit(std::shared_ptr<ASTTypeNode>(this)); // <=== HERE 
} 

thisが参照:

  • int main() 
    { 
        ASTTypeNode astTypeNode (ASTTypeNode::Type::Int); // <== this object 
        astTypeNode.accept(std::make_shared<PrintXMLVisitor>()); 
        return 0; 
    } 
    

    変更ツールチェーンは、あなたは選択肢を持ってこの問題を解決するために、2つの最も明白なビーイングを行っていません訪問パラメータにはstd::shared_ptrを使用しないでください。

  • ASTNodeTypeインスタンスをすべて管理すると、標準ライブラリのstd:enable_shared_from_this機能を使用してthisからstd::shared_ptrの管理対象となります。

これらの前者は明らかである(あるいは少なくともそれが今である)ので、私はさらにそれを議論しないでしょう。後者はshared_from_thisを利用する基底クラスのインスタンスをstd::shared_ptrラッパーによって管理する必要があるため、ではありません。つまり、あなたが現在行っているような具体的な構造はありません。main()。これは全体的なコードベースに重大な影響を与える可能性がありますので、注意深く選択してください。

あなたのケースで動作するだろうか上記の例:

まず、このように見えるようにASTNodeTypeの派生チェーンを変更します。

class ASTTypeNode 
    : public ASTNode 
    , public std::enable_shared_from_this<ASTTypeNode> // ADDED 

次に、以下のようにshared_from_thisを利用:

void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor) 
{ 
    visitor->visit(shared_from_this()); // HERE 
} 

最後に、ASTNodeTypeインスタンスが共有されているという令状を守ってください:

int main() 
{ 
    std::shared_ptr<ASTTypeNode> astTypeNode = std::make_shared<ASTTypeNode>(ASTTypeNode::Type::Int); 
    astTypeNode->accept(std::make_shared<PrintXMLVisitor>()); 
    return 0; 
} 

これでうまくいくはずです。ここでは上記のコードで使用されるものについて詳しく読む:

私はこのすべてが唯一のthisポインタ指定されたオブジェクトからstd::shared_ptrを使用して容易にすることで、言ったように。最初にその要件を削除することができれば、それはより簡単な方法かもしれませんが、まずそれを検討します。

+0

@Frac良い選択。私は同じことをやっていたでしょう。幸せな読書。 – WhozCraig

+0

最近ダウン投票した個人には、匿名投票は常に* FTLです。行動への自信のために。あなたが落選した場合、コメントに* why *を正当に正当化します。さもなければ、あなたは行動が偽りおよび/または無知とみなされます。 – WhozCraig

関連する問題