2010-06-04 3 views
6

이 코드입니다 :C++의 개체 조각화에 대한 가능한 해결 방법은 무엇입니까?

#include <string> 
#include <vector> 
#include <iostream> 
using namespace std; 
class A { 
public: 
    virtual const string f() const { return "A"; } 
}; 
class B : public A { 
public: 
    const string f() const { return "B"; } 
}; 
int main(int ac, char** av) { 
    vector<A> v; 
    v.push_back(B()); 
    cout << v.at(0).f() << endl; 
    return 0; 
} 

예상 결과가 B이지만, A을합니다. 내가 이해하는대로 개체 조각이 일어나고있다. 어떻게 피하는가? 객체 인스턴스가 아닌 vector에 포인터를 저장해야합니까? 이것이 유일한 선택일까요?

+0

개체 분할은 잘못된 결과를 초래하는 것이 아니라 멤버 연산자 (.)에 의한 함수 호출입니다. 가상 함수는 멤버 별 연산자 (->) (다음을 제외하고는 호출해야합니다. 참조를 사용할 때) – Ozan

+6

@Ozan : 말도 안돼. 다른 멤버 함수 (virtual 또는 not)에서 가상 멤버 함수를 호출하면 가상 호출이 발생합니다. – MSalters

+0

네, 저는 빈체 자에게 오브젝트 슬라이싱이 아닌 멤버 연산자를 사용하는 것이 범인이라는 것을 지적하고 싶었습니다. java/C# 사람들이 C++ – Ozan

답변

11

포인터를 저장해야합니다. 동적으로 할당 된 객체를 참조하는 경우 스마트 포인터을 사용하십시오.

3

글쎄, 코드에서 B의 벡터를 사용할 수 있습니다. 가상 함수는 포인터 또는 참조를 통해 호출 된 경우에만 올바르게 전달됩니다. 그러나 실제로 벡터에 A 및 B 객체가 모두 포함되도록하려면 A 포인터의 벡터로 만들고 A 및 B 객체를 동적으로 만들어야합니다.

11

가장 단순한 것에서부터 가장 복잡한 것까지 순서가 정해져 있습니다.

해결 방법 1 :

vector<B> v; 
v.push_back(B()); 
cout << v.at(0).f() << endl; 

해결 방법 2 :

vector<A*> v; 
v.push_back(new B()); 
cout << v.at(0)->f() << endl; 
while(!v.empty()) { delete v.back(); v.pop_back(); } 

해결 방법 3 :

vector<boost::shared_ptr<A>> v; 
v.push_back(boost::make_shared<B>()); 
cout << v.at(0)->f() << endl; 

당신이 w하지 않는 경우 개미 조각이 발생하면, 당신은 다른 개체가 서로 다른 크기를 가질 수 있다는 사실을 고려할 필요가 있습니다. 가변 크기로 작업 할 수있는 솔루션이 필요하기 때문에 힙에 반드시 저장해야합니다.

+2

'벡터 > v;'정말 좋습니다. 벡터에'auto_ptr'을 저장하지 마십시오. 복사기가 전달 된 객체를 수정합니다. 다음을 참조하십시오 : 이유 : http : //www.gotw.ca/publications/using_auto_ptr_effectively.htm. – Naveen

+0

@Naveen, 나도 알아, 아직 유일한 TR1 이전의 스마트 포인터 야. –

+0

나는 그렇게하기가 실제로 불가능하다고 확신합니다. 'std :: auto_ptr'는 컨테이너 요소에 대한 요구 사항을 충족시키지 못합니다. – sbi

관련 문제