스택-합금 객체와 함께 벡터에 이종 객체를 저장합니다
-
05-07-2019 - |
문제
스택-합금 객체와 함께 이기종 벡터에 물체를 저장합니다
안녕하십니까,
CA1, CA2 등으로 파생 된 추상 클래스 CA가 있다고 가정 해 봅시다.
이 파생 된 유형의 객체를 클래스 CB에 넣은 벡터에 넣고 싶습니다. 다형성을 올바르게 얻으려면 포인터의 벡터를 저장해야합니다.
class CB
{
std::vector <CA*> v;
};
이제 다음과 같은 주요 기능이 있다고 말합니다.
int main()
{
CB b;
CA1 a1;
CA2 a2;
b.Store( a1 );
b.Store( a2 );
}
방법을 어떻게 작성합니까? void CB::Store(const CA&)
간단한 방식으로 저장된 객체는 원래 물체가 파괴 될 때 살아남습니다 (위의 간단한 예에서는 발생하지 않음).
내 문제는 벡터에서 흡입을 복사하기 전에 힙의 객체를 먼저 복사해야한다는 것입니다. 그러나 파생 된 유형의 객체를 어떻게 만들 수 있습니까? 물론, 나는 RTTI를 사용하고 가능한 모든 유형을 검색하고 포인터를 만들고 할당하고, 벡터로 밀기 전에 할당 된 공간에 물체를 (적절한 캐스팅) 복사 할 수 있습니다. 그러나 이것은 꽤 복잡해 보입니다.
더 간단한 방법이 있습니까?
(그리고 메인에서 동적 할당을 사용하지 않고!)
해결책
일반적으로 복제 기능을 제공합니다.
struct CA
{
virtual CA *clone(void) const = 0;
virtual ~CA() {} // And so on for base classes.
}
struct CA1 : public CA
{
virtual CA *clone(void) const
{
return new CA1(*this);
}
}
struct CA2 : public CA
{
virtual CA *clone(void) const
{
return new CA2(*this);
}
}
이것을 a라고합니다 가상 생성자, 런타임에 객체의 사본을 구성 할 수 있습니다.
void CB::Store(const CA& pObject)
{
CA *cloned = pObject.clone();
}
사용 고려해야합니다 부스트 포인터 컨테이너 도서관. 코드는 다음과 같습니다.
boost::ptr_vector<CA> objects;
void CB::Store(const CA& pObject)
{
objects.push_back(pObject->clone());
}
그리고 지금 당신은 메모리를 직접 관리 할 필요가 없습니다. 도서관은 또한 복제 기능을 존중하며 객체의 사본을 만들 때 호출합니다. 여기 튜토리얼.
다른 팁
파생 클래스가 구현할 추상 클래스에서 클론 () 함수가 필요한 것 같습니다.
class CA
{
public:
virtual ~CA() {}
virtual CA* clone() const = 0;
}
class CA1 : public CA
{
public:
virtual CA *clone() const
{
return new CA1(*this);
}
};
가능성은 논증의 유형에 따라 매장을 템플릿하는 것입니다.
class CB
{
public:
template<class T>
void Store(const T& t)
{
v.push_back(new T(t));
}
private:
std::vector <CA*> v;
};
그러나 경고 : 다른 사람들이 게시 한 "Clone ()"솔루션과 달리 슬라이스가 발생하기 쉽습니다. 예를 들어, 이것은 잘 작동합니다.
CB b;
CA1 a1;
CA2 a2;
b.Store(a1);
b.Store(a2);
그러나 이것은 다음과 같습니다.
CA1 a1;
CA* a = &a1;
b.Store(*a); //Ouch! this creates a new CA, not a CA1
보호 된 사본 CTOR를 CA에 제공하면 그러한 오용을 방지합니다. 그러나 CA1을 더 하위 클래스하면 문제가 다시 발생합니다.