2013-05-11 5 views
4

저의 목표는 생성 된 모든 인스턴스를 정적 ​​멤버 컨테이너에 추가하여 모든 인스턴스에 쉽게 액세스 할 수 있도록하는 클래스를 만드는 것입니다.해당 클래스의 모든 인스턴스를 포함하는 정적 멤버 컨테이너가있는 클래스 만들기?

컨텍스트는 객체가 Game.init() 함수로 생성 된 다음 컨테이너에 추가되는 게임입니다. 그런 다음 Game.update()Game.Draw() 함수는 컨테이너를 반복하여 객체에 액세스하고 조작합니다.

수동으로 컨테이너에 /에서 개체를 추가하거나 제거하는 대신 이러한 작업을 처리하기 위해 생성자와 deconstructor를 사용하고 싶습니다.

개체 (이 코드의 상자)가 복사 또는 할당되면 문제가되는 포인터가 유효하지 않게됩니다. 개체 컨테이너에 대한 포인터 대신 개체 컨테이너를 사용하면 과도한 복사본이 만들어졌으며 참조로이 작업을 수행 할 수 없었습니다. 이러한 문제를 피하기 위해이 코드를 향상시키는 방법에 대한 팁을 찾고 있는데 포인터를 사용하지 않는 것이 좋지만 실제로이 작업을 수행하지는 않았다. 그들) :

#include <list> 
#include <iostream> 

class Box 
{ 
    private: 
     std::list <Box*>::iterator iter; 
    public: 
     static std::list <Box*> List; 
     Box() { 
      List.push_front(this); 
      iter = List.begin(); 
      std::cout << "Constructing box." << std::endl; 
     } 
     ~Box() { 
      std::cout << "Trashing box." << std::endl; 
      List.erase(iter); 
     } 
     void lookInside() { 
      std::cout << "It's empty." << std::endl; 
     }; 
}; 

std::list <Box*> Box::List; 

int main() 
{ 
    Box Box_1; 
    Box Box_2; 
    Box Box_3; 

    Box_1 = Box_2; // causes problems! 

    for (auto iter : Box::List) { 
     iter->lookInside(); 
    } 

    std::cout << "The list contains " << Box::List.size() << " boxes." << std::endl; 

    return 0; 
} 
+0

문제가 발생하지 않아야합니다. 너는 여전히 상자가 3 개있다. 방금 Box_2를 Box_1에 할당하는 것입니다. –

+0

코드가 작동하지만 종료 할 때 충돌이 발생합니다. –

+0

아하, 문제는 iter 회원입니다. –

답변

2

당신은 3/5의 규칙을 위반합니다.

클래스를 원하는대로 작동 시키려면 할당과 복사 구성을 오버로드해야합니다 (적어도). 기본 복사 생성자는 반복자를 복사하므로 원본 반복자의 사본을 포함하는 두 번째 객체로 끝나고 원본 객체를 가리키게되므로 두 사본 중 하나가 파괴되면 해당 항목이 컬렉션에서 제거됩니다.

분명히, 당신이 원하는 것은 당신의 컬렉션에 새로운 객체를 추가하고 복사본 생성이 완료되었을 때 그 객체가 컬렉션의 새로운 객체에 대한 반복자를 보유하도록하는 것입니다.

마찬가지로 기본 할당 연산자는 반복기를 원본에서 대상으로 복사합니다. 반복자를 변경하지 않고 (즉, 컬렉션에있는 동일한 객체를 계속 참조하는 것, 할당은 동일한 객체의 다른 값을 유지하므로).

#include <list> 
#include <iostream> 

class Box 
{ 
    private: 
     std::list <Box*>::iterator iter; 
    public: 
     static std::list <Box*> List; 
     Box() { 
      List.push_front(this); 
      iter = List.begin(); 
      std::cout << "Constructing box." << std::endl; 
     } 
     ~Box() { 
      std::cout << "Trashing box." << std::endl; 
      List.erase(iter); 
     } 
     void lookInside() { 
      std::cout << "It's empty." << std::endl; 
     }; 

     // JVC: added next two overloads: 
     Box &operator=(Box const &src) { 
      // don't assign anything. 
      return *this; 
     } 
     Box(Box const &other) { 
      List.push_front(this); 
      iter = List.begin(); 
      std::cout << "Copy constructing box.\n"; 
     } 
}; 

std::list <Box*> Box::List; 

int main() 
{ 
    Box Box_1; 
    Box Box_2; 
    Box Box_3; 

    Box_1 = Box_2; // No longer causes problem! 

    for (auto iter : Box::List) { 
     iter->lookInside(); 
    } 

    std::cout << "The list contains " << Box::List.size() << " boxes." << std::endl; 

    return 0; 
} 

이 전체 디자인은 실수 일 수 있습니다. 위의 코드는 버그를 비교적 미세한 수준으로 다루지 만 디자인의 기본 문제를 해결할 수있는 방법은 없습니다.

+0

대체 방법에 대한 제안이 있으십니까? –

+0

게임에 사용 된 [포인터] 개체 모음이 포함 된 게임이 좋을 것입니다. 그것은 의미가없는 게임 컬렉션을 포함하는 게임입니다 (IMO). –

관련 문제