c++ - 调用子类方法导致段错误

标签 c++ c++11 segmentation-fault pure-virtual dynamic-allocation

<分区>

我遇到了一个奇怪的问题。我写了一个 Parent 抽象类(实现了一个纯虚的 test() 方法)和它的 Child 类(实现了 test() 方法)。

class Parent
{
    public :
        Parent();
        virtual ~Parent() = default;

        virtual bool test() const = 0;
};

class Child : public Parent
{
    public :
        bool test() const;
};

然后,我编写了一个“Grid”类,它应该包含一个指向 Parent 的二维指针数组。该数组是使用 vector 库完成的:“_cells”是指向父级的指针的宽度*高度 vector 。 _cells 在 Grid 对象构造期间使用动态分配填充并在析构函数中释放。 Operator() (int a, int b) 被重载以便能够使用此模式调用父对象:myGrid(x,y)。

class Grid
{
        int _w, _h;
        std::vector<Parent*> _cells;

    public :
        Grid(int w = 0, int h = 0);
        ~Grid();
        Parent* &operator()(int x, int y);

    private :
        void generate();
};

在我的主函数中,g 是在堆栈上创建的第一个 2x2 网格。然后,它应该销毁 g 并在 g 中构造一个新的 4x4 网格。但它完全失败了:

Grid g(2, 2);
std::cout << g(1,1)->test() << std::endl; // Works perfectly
g = Grid(4, 4); // Probably wrong, but don't throw an exception
std::cout << g(1,1)->test() << std::endl; // SIGSEGV

我认为问题来自每个单元的动态分配/取消分配,但我没有找到解决它的方法。

这是我的完整代码,我没有成功地进一步简化它。我尽力了。对不起。

#include <iostream>
#include <cstdlib>
#include <vector>

class Parent
{
    public :
        Parent();
        virtual ~Parent() = default;

        virtual bool test() const = 0;
};

Parent::Parent()
{}

class Child : public Parent
{

    public :
        bool test() const;
};

bool Child::test() const
{
    return true;
}

class Grid
{
        int _w, _h;
        std::vector<Parent*> _cells;

    public :
        Grid(int w = 0, int h = 0);
        ~Grid();
        Parent* &operator()(int x, int y);

    private :
        void generate();
};

Grid::Grid(int w, int h) : _w(w), _h(h), _cells(w*h)
{
    generate();
}

Grid::~Grid()
{
    for (auto cell : _cells)
        delete cell;
}

Parent* &Grid::operator()(int x, int y)
{
    return _cells[x*_w+y];
}

void Grid::generate()
{
    int cell_num;
    for (cell_num = 0; cell_num < static_cast<int>(_cells.size()); cell_num++)
        _cells[cell_num] = new Child();
}

int main()
{
    Grid g(2, 2);
    std::cout << g(1,1)->test() << std::endl;
    g = Grid(4, 4);
    std::cout << g(1,1)->test() << std::endl;

    return 0;
}

谢谢。

最佳答案

Grid 类没有复制赋值运算符,因此将使用编译器默认生成的版本。它非常简单,只对成员进行浅拷贝。这意味着为 临时 对象创建的指针 Grid(4, 4) 被复制(只是指针,而不是它们指向的内容),并且当临时对象指针也被销毁(在临时对象的析构函数中)。这给您留下了一个对象 g,它带有指向现在已删除内存的指针。

我建议您阅读 the rule of three .

关于c++ - 调用子类方法导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22014410/

相关文章:

c++ - 演示 move 构造函数的有用性

c++ - 将模板类传递给模板函数

C++ std::system_error 与 common catch std::exception block 的用法

c++ - SPOJ SHPATH - SIGSEGV 错误

c++ - 对构造函数的调用不能出现在常量表达式中

c++ - 不能在 if 语句中直接使用 void func 将字符串转换为大写 - C++

c++ - 如何使用 C++/C++11 打印当前时间(以毫秒为单位)

c++ - 我可以使用std::array的自定义分配器来获得安全的加密 key 吗?

c - 在 C 语言中使用 GEOS API 函数返回段错误

debugging - 带pthread的电子围栏