在析构函数中调用成员变量的虚函数会导致seg错误

时间:2011-08-03 14:58:54

标签: c++ scope segmentation-fault destructor virtual-functions

我有一个非常奇怪的问题,我希望有人遇到过。

class Letter
{
public:
    Letter()
    virtual ~Letter()
    virtual std::string get() const = 0;
};

class A : public Letter
{
public:
    A()
    ~A()
    virtual std::string get() const { return "A"; }
};

class Board
{
public:
   Board(){}
   ~Board()
   {
        std::cout << "Removing: " << letter->get() << std::endl;
        delete letter;
   }
   void setLetter(Letter * l) { letter = l }
private:
   Letter * letter;
}

int main()
{
    Board b;
    b.setLetter(new A());
}

当Board在析构函数中调用虚函数letter-&gt; get()的行超出范围时,程序会导致seg错误。我正在使用gcc 4.1.2。有什么想法吗?

更新

好吧,看起来实际代码中实际发生的事情就等同于:

class Board
{
public:
   Board(){}
   ~Board()
   {
       std::cout << "Removing: " << letter->get() << std::endl;
   }
   void setLetter(Letter * l) { letter = l; }
private:
   Letter* letter;
};

int main()
{
    Board b;
    A a;
    b.setLetter(&a);

    return 0;
}

在这种情况下,当调用虚函数时,A已经超出范围。

4 个答案:

答案 0 :(得分:1)

我只能猜测你是在尝试将从get()返回的std :: string转换为char *。否则我认为没有理由崩溃。

答案 1 :(得分:0)

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

class Letter
{
public:
    Letter() {}
    virtual ~Letter() {}
    virtual std::string get() const = 0;
};

class A : public Letter
{
public:
    A() {}
    ~A() {}
    virtual std::string get() const { return "A"; }
};

class Board
{
public:
   Board(){}
   ~Board()
   {
        std::cout << "Removing: " << letter->get() << std::endl;
        delete letter;
   }
   void setLetter(Letter * l) { letter = l; }
private:
   Letter * letter;
};

int main()
{
    Board b;
    b.setLetter(new A());
    return 0;
}

gcc 4.5.2没问题。

答案 2 :(得分:0)

我没有意识到对象是从堆栈传递给setLetter()的,所以A在b之前超出了范围。

Board b;
A a;
b.setLetter(&a);

答案 3 :(得分:-1)

有些编译器不允许Plain C / C ++构造函数或析构函数调用虚方法,似乎也不像(ANSI)C ++规范。它不推荐。

有时候这个要求很有用。像Object Pascal显式这样的语言允许在构造函数和析构函数中调用虚方法。

你可以做的一件事是使用“假虚拟构造模式”:

class MyClass
{
  public:
    // constructor
    MyClass
    {
      // anything but virtual methods
    }

    // destructor
    ~MyClass
    {
      // anything but virtual methods
    }

    virtual void MyFakeConstructor()
    {
      MyVirtualMethod();
    }

    virtual void MyFakeDestructor()
    {
      MyVirtualMethod();
    }

    virtual void MyVirtualMethod()
    {
      // more stuff
    }

    // more members
}

int main(char[][] Args)
{
  MyClass MyObject = new MyClass();
  MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"

  MyObject->DoSomething1();
  MyObject->DoSomething2();
  MyObject->DoSomething3();

  MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
  delete MyObject;

  return 0;
} // int main()

另一种解决方案是,您可以安排代码,以便在析构函数之外显式调用虚方法。

干杯。