【问题标题】:C++ Constructor and DestructorC++ 构造函数和析构函数
【发布时间】:2010-12-16 16:35:19
【问题描述】:

我在编译我的程序时遇到了一些错误。它们与我的类指令的构造函数和析构函数有关。

错误是:

/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x241): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x2ab): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x315): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x38d): undefined reference to `vtable for Instruction'
collect2: ld returned 1 exit status

这是我的代码:

//classses.h

#include <iostream>
#include <string>
using namespace std;

class Instruction{

  protected:
    string name;
    int value;

  public:
    Instruction(string _name, int _value);
    ~Instruction();
    void setName(string _name);
    void setValue(int _value);
    string getName();
    int getValue();
    virtual void execute();
};

//constructor
Instruction::Instruction(string _name, int _value){
    name = _name;
    value = _value;
}
//destructor
Instruction::~Instruction(){
    name = "";
    value = 0;
}
void Instruction::setName(string _name){
     name = _name;
}

void Instruction::setValue(int _value){
    value = _value;
}

string Instruction::getName(){
       return name;
}

int Instruction::getValue(){
    return value;
}

/////////////////////////////////////// ///////////////////////p>

//ale.cpp

    #include "headers.h"
    #include "functions.h"
    #include "classes.h"
    #include <list>


    using namespace std;

    int main(){

    return 0;
    }

【问题讨论】:

  • 您用来编译和链接程序的命令行是什么?
  • 在不相关的注释中,如果您想在标头内的类之外定义函数/方法,请给它们inline 说明符。
  • 旁注:你不需要那个析构函数。没有必要“清零”您的数据。
  • 但是拥有一个虚拟析构函数可能是个好主意,因为这显然是一个基类。

标签: c++ g++ constructor destructor


【解决方案1】:

我猜这个问题是由于您在指令类中声明了一个虚拟方法“执行”,而从未在任何地方定义它。编译器必须为具有虚方法的类生成一个 vtable 对象,并且实际上只需要它的一个副本,因此他们通常只在定义第一个虚函数的编译单元(源文件)中进行...

【讨论】:

    【解决方案2】:

    您没有定义您的虚函数和/或 g++ 希望您将析构函数设为虚拟(因为您有假设继承的虚函数)

    【讨论】:

    • 顺便说一句,在析构函数中分配空字符串或零是没有意义的。它的目的是销毁数据,而不是重新初始化它。在你的情况下,空析构函数就足够了
    • 析构函数不必是虚拟的(例如,它不会产生编译器错误),它应该是parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7
    • 这就是为什么我把它放在我的回复的第二部分:) 我想问题是他的虚函数没有定义,但是C++编译器是如此脆弱的物种......
    • 另一方面,析构函数可以被保护而不是虚拟的,这也可以。
    • 对不起?如果析构函数不是虚拟的,那么当你删除一个对象时,你会调用一个由变量类型指定的析构函数,而不是对象的实际类型。受保护的析构函数不会使其成为虚拟的,充其量只会产生编译错误。
    【解决方案3】:

    试试

    virtual void execute()=0;
    

    这将使您的类抽象,这似乎是您想要的,因为未定义执行。

    如果您想在多个 .cpp 文件中使用指令,则应将类方法的实现移动到 classes.cpp 文件中。

    【讨论】:

      【解决方案4】:

      正如人们已经说过的,问题在于未实现的 execute()。实现它,或者像 Dan Hook 所说的那样让它成为纯虚拟的。

      只是一个额外的说明:在许多情况下(可能大部分取决于您正在编码的内容),您不需要实现析构函数。如果你想要一些特定的功能(例如将数据刷新到文件),你只需要。

      只要您没有指针(就像您的代码中的情况一样),您就不会有任何内存跟踪问题。只需删除析构函数:它是安全的,而且代码更少。 但是,如果只有一个成员是指针,那么一切都会变得一团糟,您必须处理内存管理问题、内存泄漏和段错误;)

      【讨论】:

      • -1 如果类有任何虚拟成员,派生类实例很可能会通过指向基的指针被删除。在这种情况下,肯定也需要一个虚拟析构函数。 - 但是,它的实现可以是空的。通过在父析构函数的末尾自动调用其析构函数来销毁字符串成员,并在此之前将其设置为空字符串。
      猜你喜欢
      • 2011-04-03
      • 2012-04-10
      • 2012-11-14
      • 2016-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-07
      • 2014-05-27
      相关资源
      最近更新 更多