2011-10-20 2 views
1

글쎄, 문제는 클래스 룸을 TransparentMaze 클래스의지도에 넣을 때 내 방 클래스가 문자열 변수 "name"값을 잃어 버리는 것입니다. 나는 그들이 어디로 갈지 이해할 수 없다. 문제는지도 비교기 또는 다른 것과 관련되어 있는가, 누군가가 도울 수 있기를 바란다.클래스 문자열 변수가 다른 클래스의지도에 해당 클래스를 넣을 때 해당 값을 잃습니다.

#include <iostream> 
#include <string> 
#include <list> 
#include <map> 

using namespace std; 

class Point{ 
    int x; 
    int y; 
    public: 
     Point(int, int); 
     ~Point(){}; 
     int getX() ; 
     int getY() ; 
}; 

struct cmp_str { 
    bool operator()(Point p1, Point p2) { 
     if (p1.getY() < p2.getY() || p1.getY() == p2.getY() && p1.getX() < p2.getX()) { 
      return true; 
     } 
     return false; 
    } 
}; 

class Room{ 
    Room *north; 
    Room *south; 
    Room *east; 
    Room *west; 
    public: 
     int createDirection[4]; 
     std::string name; 
     Room(std::string); 
     ~Room(); 
     std::string getName(); 
     std::list<std::string> findPathTo(std::string); 
     void fillMap(map<Point, Room*, cmp_str>*, int*, int*); 
     Room& createNorth(std::string); 
     Room& createSouth(std::string); 
     Room& createEast(std::string); 
     Room& createWest(std::string); 
     Room& getNorth(); 
     Room& getSouth(); 
     Room& getEast(); 
     Room& getWest(); 
     Room& get(std::string); 
     Room& get(std::list<std::string>); 
     void setNorth(Room*); 
     void setSouth(Room*); 
     void setEast(Room*); 
     void setWest(Room*); 
     //bool validatePath(std::list<std::string>); 
}; 

class Maze{ 
    Room *entry; 
    public: 
     Maze(string); 
     ~Maze(); 
     Room& getEntry(); 
}; 

class TransparentMaze{ 
    std::map<Point, Room*, cmp_str> maze; 
    int width; 
    int height; 
    public: 
     TransparentMaze(Maze); 
     ~TransparentMaze(){}; 
     std::map<Point, Room*, cmp_str>& getMaze(); 
}; 

TransparentMaze::TransparentMaze(Maze maze) { 
    maze.getEntry().fillMap(&this->maze, &this->width, &this->height); 
} 

std::map<Point, Room*, cmp_str>& TransparentMaze::getMaze() { 
    return maze; 
} 

Point::Point(int x, int y) { 
    this->x = x; 
    this->y = y; 
} 

int Point::getX() { 
    return x; 
} 

int Point::getY() { 
    return y; 
} 

Maze::Maze(std::string name) { 
    entry = new Room(name); 
} 

Maze::~Maze() { 
    delete entry; 
} 

Room& Maze::getEntry() { 
    return *entry; 
} 

Room::Room(std::string name) { 
    this->name = name; 
    for (int i = 0; i < sizeof(createDirection)/sizeof(int); i++) { 
     createDirection[i] = 0; 
    } 
    north = NULL; 
    south = NULL; 
    east = NULL; 
    west = NULL; 
} 

Room::~Room() { 
    for (int i = 0; i < sizeof(createDirection)/sizeof(int); i++) { 
     switch(i) { 
      case 0: 
       if (createDirection[i] == 1) { 
        delete north; 
       } 
       break; 
      case 1: 
       if (createDirection[i] == 1) { 
        delete south; 
       } 
       break; 
      case 2: 
       if (createDirection[i] == 1) { 
        delete east; 
       } 
       break; 
      case 3: 
       if (createDirection[i] == 1) { 
        delete west; 
       } 
       break; 
     } 
    } 
} 

Room& Room::get(std::string direction) { 
    switch(direction[0]) { 
     case 'N': case 'n': return (this->north == NULL ? *this : *this->north); 
     case 'S': case 's': return (this->south == NULL ? *this : *this->south); 
     case 'E': case 'e': return (this->east == NULL ? *this : *this->east); 
     case 'W': case 'w': return (this->west == NULL ? *this : *this->west); 
     default: break; 
    } 
    return *this; 
} 

Room& Room::get(std::list<std::string> pathList) { 
    std::list<std::string>::iterator it; 
    Room *room = this; 

    for (it = pathList.begin(); it != pathList.end(); it++) { 
     if (&(*room) == &room->get(*it)) { 
      return *this; 
     } 
     room = &room->get(*it); 
    } 
    return *room; 
} 

void Room::fillMap(map<Point, Room*, cmp_str> *maze, int *width, int *height) { 
    std::list<std::list<std::string>> listOfLists; 
    std::list<std::list<std::string>>::iterator it1; 
    Room *r; 
    int n, counter; 

    *width = *height = 0; 
    listOfLists.push_back(std::list<std::string>()); 
    for (;;) { 

     counter = 0; 
     for (it1 = listOfLists.begin(); it1 != listOfLists.end(); it1++) { 
      r = &this->get(*it1); 

      //Point p((int)r->getName()[0] - 64, (int)r->getName()[1] - 48); 
      //cout << r->getName() << " " << &*r << " " << &this->get(*it1) << endl; 
      maze->insert(std::make_pair(Point((int)r->getName()[0] - 64, (int)r->getName()[1] - 48), &*r)); 
      //cout << r->getName() << endl; 
      std::string lastRoom; 
      n = 0; 

      if (it1->size() > 0) { 
       lastRoom = *--it1->end(); 
      } 
      if (&r->getNorth() != NULL && lastRoom.compare("S") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("N"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("N"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getEast() != NULL && lastRoom.compare("W") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("E"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("E"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getWest() != NULL && lastRoom.compare("E") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("W"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("W"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getSouth() != NULL && lastRoom.compare("N") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("S"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("S"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
     } 

     if(counter == 0) { 
      /*cout << listOfLists.size() << endl; 
      map<Point, Room*, cmp_str>::iterator it; 
      for (it = maze->begin(); it != maze->end(); it++) { 
       cout << "X: "<< it->first.getX() << " Y: " << it->first.getY() << "; " << (*it->second).getName() << endl; 
      }*/ 
      return; 
     } 
    } 
} 

std::list<std::string> Room::findPathTo(std::string roomName) { 
    std::list<std::list<std::string>> listOfLists; 
    std::list<std::list<std::string>>::iterator it1; 
    Room *r; 
    int n, counter; 

    listOfLists.push_back(std::list<std::string>()); 
    for (;;) { 

     counter = 0; 
     for (it1 = listOfLists.begin(); it1 != listOfLists.end(); it1++) { 
      r = &this->get(*it1); 
      std::string lastRoom; 
      n = 0; 

      if (it1->size() > 0) { 
       lastRoom = *--it1->end(); 
      } 
      if (r->getName().compare(roomName) == 0) { 

       return *it1; 
      } 
      if (&r->getNorth() != NULL && lastRoom.compare("S") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("N"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("N"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getEast() != NULL && lastRoom.compare("W") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("E"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("E"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getWest() != NULL && lastRoom.compare("E") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("W"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("W"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
      if (&r->getSouth() != NULL && lastRoom.compare("N") != 0) { 
       n++; 
       counter++; 
       if (n == 1) { 
        it1->push_back("S"); 
       } else { 
        std::list<std::string> bufferList(it1->begin(), --it1->end()); 
        bufferList.push_back("S"); 
        listOfLists.push_back(bufferList); 
       } 
      } 
     } 

     if(counter == 0) { 
      return std::list<std::string>(); 
     } 
    } 
} 

/*bool Room::validatePath(std::list<std::string> pathList) { 
    std::list<std::string>::iterator it; 
    Room *room = this; 

    for (it = pathList.begin(); it != pathList.end(); it++) { 
     if (&(*room) == &room->get(*it)) { 
      return false; 
     } 
     room = &room->get(*it); 
    } 
    return true; 
}*/ 

std::string Room::getName(){ 
    return name; 
} 

Room& Room::createNorth(std::string name) { 
    north = new Room(name); 
    createDirection[0] = 1; 
    north->setSouth(this); 
    return *north; 
} 

Room& Room::createSouth(std::string name) { 
    south = new Room(name); 
    createDirection[1] = 1; 
    south->setNorth(this); 
    return *south; 
} 

Room& Room::createEast(std::string name) { 
    east = new Room(name); 
    createDirection[2] = 1; 
    east->setWest(this); 
    return *east; 
} 

Room& Room::createWest(std::string name) { 
    west = new Room(name); 
    createDirection[3] = 1; 
    west->setEast(this); 
    return *west; 
} 

Room& Room::getNorth() { 
    return *north; 
} 

Room& Room::getSouth() { 
    return *south; 
} 

Room& Room::getEast() { 
    return *east; 
} 

Room& Room::getWest() { 
    return *west; 
} 

void Room::setNorth(Room *room) { 
    north = room; 
} 

void Room::setSouth(Room *room) { 
    south = room; 
} 

void Room::setEast(Room *room) { 
    east = room; 
} 

void Room::setWest(Room *room) { 
    west = room; 
} 

int main() { 
    Maze maze("A5"); 

    maze.getEntry().createSouth("A6").createEast("B6").createSouth("B7").createWest("A7") 
     .getEast().createEast("C7").createNorth("C6").createEast("D6").createEast("E6") 
     .getWest().createNorth("D5").createEast("E5").getWest().getSouth().getWest() 
     .createNorth("C5").createWest("B5").createNorth("B4").createWest("A4").createNorth("A3") 
     .getSouth().getEast().getSouth().getEast().createNorth("C4").createNorth("C3") 
     .createWest("B3").getEast().createNorth("C2").createWest("B2").createWest("A2") 
     .createNorth("A1").getSouth().getEast().getEast().createEast("D2").createSouth("D3") 
     .createSouth("D4").createEast("E4").createNorth("E3").createNorth("E2").createNorth("E1") 
     .createWest("D1").createWest("C1").createWest("B1").getEast().getEast().getEast() 
     .createEast("F1").createEast("G1").createEast("H1").createSouth("H2").createEast("I2") 
     .createSouth("I3").createEast("J3").createNorth("J2").createNorth("J1").createWest("I1") 
     .getEast().getSouth().getSouth().getWest().getNorth().getWest().getNorth().getWest() 
     .getWest().getWest().getSouth().getSouth().createEast("F3").createEast("G3") 
     .createNorth("G2").createWest("F2").getEast().getSouth().createEast("H3").createSouth("H4") 
     .createEast("I4").createEast("J4").createSouth("J5").createWest("I5").createWest("H5") 
     .getEast().createSouth("I6").createEast("J6").createSouth("J7").createWest("I7") 
     .createWest("H7").createWest("G7").getEast().createNorth("H6").createWest("G6") 
     .createWest("F6").createNorth("F5").createNorth("F4").createEast("G4").createSouth("G5") 
     .getNorth().getWest().getSouth().getSouth().createSouth("F7").createWest("E7") 
     .createWest("D7"); 

    //cout << (int)'A' << endl; 
    //cout << (int)'1' << endl; 

    /*std::list<std::string> list(maze.getEntry().findPathTo("E7")); 
    std::list<std::string>::iterator it; 

    for (it = list.begin(); it != list.end(); it++) { 
     cout << *it << endl; 
    }*/ 

    //cout << sizeof(maze.getEntry()) << endl; 



    //Here it has still a value.. 
    cout << maze.getEntry().getName().length() << endl; 
    TransparentMaze tMaze(maze); 
    //Here not anymore.. why it's gone? 
    cout << maze.getEntry().getName().length() << endl; 




    //tMaze.getMaze(); 
    /*map<Point, Room*, cmp_str>::iterator it; 
    for (it = tMaze.getMaze().begin(); it != tMaze.getMaze().end(); it++) { 
     cout << "X: "<< it->first.getX() << " Y: " << it->first.getY() << "; " << it->second->name << endl; 
    }*/ 


} 
+0

당신은 ... 기대하고, 당신은 ??? 문제는 무엇입니까? –

+0

이 글을 읽고 그에 따라 게시물을 편집하십시오 : [SSCCE] (http://sscce.org/) – ildjarn

+0

많은 코드가 있지만 구체적인 질문을하고 (간략히), 간결한 컴파일 가능한 예제를 제공합니다. – Chad

답변

1

이것은 다소 복잡하지만 여기서는 어떤 일이 일어나고 있는지 알려드립니다. 간단히 말해 TransparentMaze 생성자는 Maze 인스턴스가 값으로 전달되지만 Maze 클래스는 복사 할 수 없습니다 (포인터가 포함되어 있음). 이 문제를 해결하는 가장 간단한 방법은 Maze을 복사 할 수 없도록 설정하고 TransparentMaze를 복사본 대신 Maze (Maze&)을 참조하는 것입니다. TransparentMaze가 구성되어

class Maze{ 
    Room *entry; 

    // these two lines make it non-copyable 
    Maze(const Maze&);   // <-- private copy constructor 
    Maze& operator=(const Maze&); // <-- private assignment operator 

    public: 
     Maze(string); 
     ~Maze(); 
     Room& getEntry(); 
}; 


class TransparentMaze{ 
    std::map<Point, Room*, cmp_str> maze; 
    int width; 
    int height; 
    public: 
     TransparentMaze(Maze&); // pass by reference 
     ~TransparentMaze(){}; 
     std::map<Point, Room*, cmp_str>& getMaze(); 
}; 

TransparentMaze::TransparentMaze(Maze& maze) { 
    maze.getEntry().fillMap(&this->maze, &this->width, &this->height); 
} 

, 생성자는 entry 포인터의 복사본을 만듭니다 Maze의 사본을 가져옵니다. 이 복사본은 TransparentMaze 생성자가 완료되고 ~Maze 소멸자가 entry 포인터를 삭제하면 삭제됩니다. 그 후에 삭제 된 entry 포인터를 사용하려고하면 원래 maze 인스턴스에서 복사 된 것입니다. 시스템에서 충돌이 발생합니다. 정의되지 않은 동작이 발생합니다.

0

많은 코드가 있습니다. 거기에 많은 문제가 있지만 실제 문제는 이것입니다 - 개체가 얕은 복사본을 수행하고 파괴시 스스로를 정리합니다. 이 방법으로 사용되는 얕은 사본은 제대로 작동하지 않습니다. 하나의 사본이 파손될 때 객체의 후속 사본에서 가리킨 메모리가 해제되어 남아있는 객체에 포인터가 매달리게됩니다.

// This function takes a COPY of the Maze object 
TransparentMaze::TransparentMaze(Maze maze) 

// But the Maze object cannot be safely copied 
// because it only does a shallow copy 
// and destroy's its entry upon destruction 
Maze::~Maze() { 
    delete entry; 
} 

포인터 유형을 스마트하는 MazeRoom에 원시 포인터를 이동하는 것을 고려, 또는 당신은 당신의 모든 클래스에 대한 copy-constructors를 작성해야합니다.

딥 복사 대 얕은 복사에 대한 설명은 this question을 참조하십시오.

+0

고맙습니다. 이제 실수를 보았습니다. TransparentMaze 클래스 내에서 Maze 클래스 참조를 전달해야합니다. 이제 작동합니다. – Jaak

관련 문제