Question

Je suis confronté à un problème étrange.J'ai écrit une classe abstraite Parent (implémentant une méthode test() virtuelle pure) et sa classe Child (implémentant la méthode test()).

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

        virtual bool test() const = 0;
};

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

Ensuite, j'ai écrit une classe "Grid" qui est censée contenir un tableau à deux dimensions de pointeurs vers Parent.Le tableau est réalisé à l'aide de la bibliothèque vectorielle :"_cells" est un vecteur largeur*hauteur de pointeurs vers Parent._cells est rempli lors de la construction de l'objet Grid à l'aide d'une allocation dynamique et libéré dans le destructeur.Operator() (int a, int b) est surchargé afin de pouvoir appeler l'objet Parent en utilisant ce modèle :maGrille(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();
};

Dans ma fonction principale, g est une première grille 2x2 créée sur la pile.Ensuite, il est censé détruire g et construire une nouvelle grille 4x4 en g.Mais cela échoue complètement :

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

Je pense que le problème vient de l'allocation/désallocation dynamique de chaque cellule, mais je n'ai pas trouvé de moyen de le résoudre.

Voici mon code complet, je n'ai pas réussi à le simplifier davantage.J'ai fait de mon mieux.Désolé.

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

Merci.

Était-ce utile?

La solution

Le Grid La classe n'a pas d'opérateur d'affectation de copie, donc la version générée par défaut du compilateur sera utilisée à la place.C'est très simple et ne fait qu'une copie superficielle des membres.Cela signifie que les pointeurs créés pour le temporaire objet Grid(4, 4) sont copiés (uniquement les pointeurs, et non ce vers quoi ils pointent), et lorsque l'objet temporaire est détruit, les pointeurs le sont également (dans le destructeur de l'objet temporaire).Cela vous laisse avec un objet g avec des pointeurs vers la mémoire maintenant supprimée.

Je vous suggère de lire sur la règle de trois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top