2012-09-29 3 views
0

그래서 내가 잘 오버로드는 = 연산자 역설

Class Person{ 
private: 
    Person* _friends[10]; 
public: 
//All methods listed below. Except for the main one, that is. 
} 
Person::Person() 
{ 
    for(int i=0; i < 10; i++) 
     _friends[10] = 0; 
} 
Person* Person::getFriends() 
{ 
    return _friends; 
} 
void Person::addFriend(Person* buddy) //Assume it's fully functional. 
{ 
    //code for adding a friend. 
} 
void Person::operator=(Person& p) 
{ 
    for(int i = 0; i < 10; i++) 
     _friends[i] = p.getFriends()[i]; 
} 

int main() 
{ 
    int user1size = 10; 
    int user2size = 30; 
    Person* user1 = new Person[10]; 
    Person* user2 = new Person[10]; 

    //assume these 4 next lines will be repeated with different values a few more times, in more intricate ways, by the magic of for/while loops. 
    user1[0] = new Person(); 
    user2[9] = new Person(); 
    user1[0].addFriend(user[9]); 
    user1[9].addFriend(user[0]); 

    for(int i = 0; i < user1size; i++) 
    { 
     user2[i] = user1[i]; //Here is where the paradox starts. 
    } 

    delete [] user1; 
return 0; 
} 

이 있다고, 내 질문은 어디에 중지 않습니다입니까? 내 의도는 _friends 배열 안의 Person 객체에 대한 참조 만 복사하는 것입니다.하지만 가능하지 않을 수도 있음을 알고 있습니다. 따라서이 Person 객체도 "복사"하는 것이 솔루션입니다. 친구 목록, 그리고이 친구들도 친구를 가지고 있습니다. 나는 어딘가에서 멈춰야 만한다는 것을 알고 있지만, 실제로 그것을 완전히 끝내기를 원하지는 않는다. 심지어 Person 객체가 복사되지 않거나 무한 루프에 빠지기를 바라지 않는다. 어떻게이 역설을 해결할 수 있습니까?

P. : 제 코드에 많은 실수가 있거나 엉터리라고 이해해주십시오. 나는 그것을 이동 중에 만들었고 내가 의도 한 것은 당신 모두가 일반적인 아이디어를 잡는 것입니다.

P.S.2 : <ostream> 이외의 라이브러리를 사용할 수 없으므로 나를 괴롭 힙니다.

P.S.3 :이 웹 사이트에서 기사를 읽으면서 제공 할 수있는 웹 사이트 나 기사는 저를 매우 행복하게 만들 것입니다. 미리 감사드립니다.

+0

코드를 들여 씁니다. –

+0

잘 들여 쓰여지고 실제로 컴파일 될 코드를 게시하십시오. 나는 대문자 "Class"가 괜찮은지 의심스럽고 addFriend을 private으로 만들었으므로 main()에서 호출 할 수 없습니다. 당신이 그렇게 할 때까지는, 당신의 단락을 읽는 것이 너무 귀찮습니다. –

+0

그래, 내가 고칠거야, 내가 말했듯이, 나는 가야했다. – Yokhen

답변

3

글쎄, 우선, 포인터를 그대로 복사하는 것이 좋습니다.

왜? 사람 "A"에 친구 "F"가 있고 사람 "B"에 친구 "F"가있는 경우에도 동일한 사람 "F"개체를 참조하게됩니다. 당신이 제안한 것처럼 깊은 사본을 만들고 A에서 A2와 B를 B2로 복사하면 A와 B로부터 참조 된 원본 인 A와 B에서 참조 된 사본이 총 3 개의 별개 인 "F"개체가됩니다. A2와 B2에서 참조 된 다른 사본.

물론 이것은 원하는 것일 수 있습니다. 나는 그것을 알 수 없다. 그러나 많은 경우에 그렇지 않습니다. 당신은 메모리 관리에주의 할 필요가 있지만,

전체 포인터 설정은 잘 작동합니다 : 당신이 깊은 복사를 수행 할 경우 당신은 쉽게 (더 이상

을 존재하지 않는 사람에 대한 포인터로 끝날 수 있습니다 "딥 카피 (deep copy)"는 참조 된 객체가 복사되는 사본입니다), 이미 복사 한 객체를 추적하는 것과 같은 방법으로 스스로를 찾아야합니다. 나는 다소 복잡해질 수 있기 때문에 지금이 같은 것을 스케치하려고하지 않을 것입니다. 그리고 나는 당신이 실제로 당신의 "person"객체를 깊게 복사하려고한다고 생각하지 않습니다.

0

IIUC 개체의 그래프 복사본을 처리하는 방법을 알고 그래프에서 연결을 유지하려고합니다. Joe에게 친구 Bill이 있고 Bill에 Joe라는 친구가 있고 Joe를 복사한다고 가정 해 봅시다. Joe에게 친구 인 Joe를 친구로두고 싶습니다. 이 문제는 일반적으로 컴파일러를 프로그래밍 할 때 발생합니다.

실제로 이렇게하는 가장 쉬운 방법은 절대로 복사본을 만드는 것이 아닙니다. 객체를 메모리 위치에두고, 참조/포인터를 항상 사용하고 파괴적으로 수정합니다.

그러나 개체를 복사하여 그래프를 수정할 필요가있을 때가 있습니다 (컴파일러 시나리오에서 함수를 인라인하는 것을 의미 할 수도 있음). 이 경우에는 대략 다음과 같이 간단한 그래프 순회 알고리즘의 DFS를 사용 : 당신은 그냥 새 위치로 어떤 객체를 이동하려면

// o will be the object to copy 
// m will be a map (old object -> new object) 
copy(object* o, map& m) { 
    if(m.contains(o)) 
    return m[o]; 
    object* n = allocate new object; 
    m[o] = n; // set the map beforehand, in case we have some back edges from this subtree 
    n.subobject = copy(o.subobject, m); // for each subobject, or relation. In your case, friend 
    return n; 
} 

, 당신은 단지 전체 그래프를 통과하고, 포인터를 덮어 쓸 수 있습니다 . 그래프의 뒷쪽 가장자리가있는 경우 (예 : "친구"뿐만 아니라 "내가있는 친구"인 경우) 훨씬 쉽습니다.여전히 최선의 선택은 그것을 피하는 것입니다. 즉 Person의 배열을 생성하지 않고 배열을 Person*으로 만들지 않기 때문에 실제 Person은 여전히 ​​같은 메모리 위치에 있습니다.

1

깊은 사본을 작성하지 않으므로 역설이 없습니다.

Person* _friends[10]; 

이 _friends가 포인터Person에 객체의 배열 말한다 :이 선언을 확인하십시오. 이 배열 operator=()에서 올바르게 복사하면 이 아닌이 배열의 각 Personoperator=()을 호출합니다.

그러나, 다음 함수는 컴파일되지 않습니다 :

Person* Person::getFriends() 
{ 
    return _friends; 
} 

반환 형식과 일치하지 않는 _friends의 유형입니다. 따라서 발생한 문제를 컴파일하고 정확하게 재현하는 코드를 게시하는 것이 중요합니다.

+0

1. 감사합니다. 그건 내 영혼을 진정시켜. 2. 반환 유형은 무엇이되어야합니까? (그게 또 다른 작은 문제입니다.) 3.'Person's의 소멸자에서'(int i = 0; i <10; i ++) if (_myWorkouts [i]! = NULL)) delete _friends [i];'포인터 나 객체를 삭제합니까? 아니면 일반적으로, 그것은 무엇을합니까? 고맙습니다. – Yokhen

+0

이것은'getFriends()'의 리턴 타입을 변경하는 것보다 더 복잡합니다. C++에서는 배열을 반환 할 수 없습니다. 아마도 질문을 수정하거나 새로운 질문을 게시해야합니다. 나는 여기서 답을 타이핑하기 시작했으나 간단한 설명을하기에는 너무 길다. –

+0

p.s. 당신의 영혼이 얼마나 평온 해 졌는지 정확하게 나타낼 것입니다 :-) –

관련 문제