0

이상한 문제가 있습니다. 나는 부모 추상 클래스 (순수 가상 test() 메소드 구현)와 Child 클래스 (test() 메소드 구현)를 썼다.하위 클래스 메서드를 호출하면 분할 오류가 발생합니다.

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

     virtual bool test() const = 0; 
}; 

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

그런 다음 필자는 Parent에 대한 포인터의 2 차원 배열을 포함해야하는 "Grid"클래스를 작성했습니다. 배열은 벡터 라이브러리를 사용하여 수행됩니다. "_cells"는 Parent에 대한 포인터의 너비 * 높이 벡터입니다. _cells는 동적 할당을 사용하여 Grid 객체를 생성하는 동안 채워지고 소멸자에서 해제됩니다. 이 패턴 (myGrid (x, y))을 사용하여 Parent 객체를 호출 할 수 있도록 Operator() (int a, int b)가 오버로드됩니다.

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 

나는 문제가 각 셀의 동적 할당/desallocation에서 오는 것으로 생각하지만, 나는 그것을 해결하는 방법을 찾을 수 없습니다.

여기 내 전체 코드가 있습니다. 더 단순화하는 데는 성공하지 못했습니다. 나는 최선을 다 했어. 죄송합니다.

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

감사합니다.

+4

3의 규칙 (C++ 11에서 5)을 위반하면서 무엇을 기대합니까? –

+0

'g = Grid (4, 4); '를 사용하는 것처럼 그리드를 다른 그리드에 지정하려면, Grid 클래스에 대해'operator ='를 정의하는 것이 좋습니다. –

답변

4

Grid 클래스에는 복사 지정 연산자가 없으므로 컴파일러의 기본 생성 버전이 대신 사용됩니다. 그것은 매우 간단하며, 구성원의 얕은 복사 만합니다. 이는 임시 포인터 개체 Grid(4, 4)에 대해 생성 된 포인터가 복사된다는 것을 의미합니다 (포인터는 가리키는 포인터가 아니라 포인터 임). 임시 개체가 소멸되면 포인터도 임시 개체의 소멸자에서 복사됩니다. 이로 인해 이제 삭제 된 메모리에 대한 포인터가있는 객체 g이 남습니다.

the rule of three을 읽어 보시기 바랍니다.