2017-05-01 117 views
1

我正在C++中實現Visitor類,它爲分析樹生成XML輸出。未定義對'vtable for class'的引用

當我在Windows上使用Clion進行編譯時,代碼會編譯,但是當它運行後,它會輸出預期會崩潰的代碼。錯誤代碼是這個

進程退出代碼爲-1073741819(0000005)

完成當我嘗試用gcc(不克利翁)編譯我得到錯誤信息

未定義參考'PrintXMLVisitor的vtable'。

我的代碼如下。我已蒸餾下來到最少的產生錯誤

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 

ASTTypeNode.cpp

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

更改工具鏈是不會解決這個問題,你有選擇,這兩個最明顯的是:

  • 停止使用std::shared_ptr作爲visit參數。
  • 使用標準庫的std:enable_shared_from_this功能管理所有ASTNodeType實例需要被std::shared_ptr管理並從this共享。

前者是顯而易見的(或者至少是現在),所以我不會再討論它。後者是而不是必然是微不足道的,因爲它要求任何使用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實例共享的權限-ptr通過執行此操作來管理:

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

相關問題