Pregunta

Estoy enfrentando un problema extraño.Escribí una clase abstracta principal (implementando un método test() virtual puro) y su clase secundaria (implementando el método test()).

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

        virtual bool test() const = 0;
};

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

Luego, escribí una clase "Grid" que se supone que contiene una matriz bidimensional de punteros a Parent.La matriz se realiza utilizando la biblioteca de vectores:"_cells" es un vector ancho*alto de punteros a Padre._cells se llena durante la construcción del objeto Grid mediante asignación dinámica y se libera en el destructor.Operador() (int a, int b) está sobrecargado para poder llamar al objeto principal usando este patrón:miGrid(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();
};

En mi función principal, g es una primera cuadrícula de 2x2 creada en la pila.Luego, se supone que debe destruir g y construir una nueva cuadrícula de 4x4 en g.Pero falla completamente:

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

Creo que el problema proviene de la asignación/desasignación dinámica de cada celda, pero no encontré una manera de resolverlo.

Aquí está mi código completo, no logré simplificarlo más.Hice mi mejor esfuerzo.Lo siento.

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

Gracias.

¿Fue útil?

Solución

El Grid La clase no tiene un operador de asignación de copia, por lo que en su lugar se utilizará la versión generada por defecto del compilador.Es muy simple y sólo hace una copia superficial de los miembros.Eso significa que los punteros creados para el temporario objeto Grid(4, 4) se copian (solo los punteros, y no lo que apuntan), y cuando el objeto temporal se destruye también lo son los punteros (en el destructor del objeto temporal).Esto te deja con un objeto. g con punteros a la memoria ahora eliminada.

Te sugiero que leas sobre la regla de tres.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top