템플릿 전문화는 최상의 대답이며 노드 유형을 혼합하지 않는 한 잘 작동합니다. 그러나 링크 된 노드의 유형을 혼합하려는 경우이를 수행하는 방법을 보여줍니다. 첫째, 간단한 템플릿 솔루션이 없습니다. 엄격한 유형 제한 때문에 링크 된 노드를 함께 입력해야합니다.
아주 일반적인 해결책은 variant 클래스를 구성하는 것입니다 (variant 유형으로 하나의 값을 보유 할 수 있으며 항상 어느 것이지 알고 있습니다). Qt는 예를 들어 QVariant 클래스입니다. 부스트는 boost::any입니다.
다음은 모든 유형을 보유 할 수있는 맞춤 변형 클래스를 사용하는 완전한 구현 예입니다. 나는 당신이 제안한 객체 포인터와 열거 형을 처리 할 수 있지만 더 많이 보유하기 위해 확장 될 수있다. 인쇄 번 "OBJ 삭제"합니다
예 :
#include <iostream>
int
main(int argc, char **argv)
{
LinkedList<VariantExample> elementObj(new ExampleObj);
LinkedList<VariantExample> elementEnum(enumOne);
elementEnum.setNext(elementObj);
}
// VariantExample class. Have a look at [QVariant][4] to see how a fairly
// complete interface could look like.
struct ExampleObj
{
};
enum ExampleEnum
{
enumOne,
enumTwo
};
struct VariantExample
{
ExampleObj* obj; // or better boost::shared_ptr<ExampleObj> obj
ExampleEnum en;
bool is_obj;
bool is_enum;
VariantExample() : obj(0), is_obj(false), is_enum(false) {}
// implicit conversion constructors
VariantExample(ExampleObj* obj_) : is_obj(true), is_enum(false)
{ obj = obj_;
}
VariantExample(ExampleEnum en_) : obj(0), is_obj(false), is_enum(true)
{ en = en_;
}
// Not needed when using boost::shared_ptr above
void
destroy()
{
if(is_obj && obj)
{
std::cout << "delete obj" << std::endl;
delete obj;
}
}
};
// The linked list template class which handles variant classes with a destroy()
// method (see VariantExample).
template
<
typename _type_ = VariantExample
>
struct LinkedList
{
LinkedList* m_next;
_type_ m_variant;
explicit
LinkedList(_type_ variant_) : m_next(0), m_variant(variant_){ }
void
setNext(LinkedList& next_){ m_next = &next_; }
// Not needed when using boost::shared_ptr above
~LinkedList()
{
m_variant.destroy();
}
};
을 elementObj의 파괴 방법은 한 번 LinkedList의의 소멸자가 호출 될 때 호출하기 때문에, 출력은 한 번만 나타나고있다 "obj가 삭제". 다시 말하지만, 삭제/소유권에 대해 구체적으로 설명 했으므로이 예제에는 destroy 메소드/인터페이스가 있습니다. LinkedList 클래스의 소멸자에서 명시 적으로 호출됩니다. 즉, 더 나은 소유권 모델을 구현할 수 있습니다. boost::shared_ptr. 그렇다면 수동으로 파괴 할 필요가 없습니다. 그것은 conversion constructors에 대해 읽는 것을 돕습니다.
// the first parameter becomes boost::shared_ptr<ExampleObj>(new ExampleObj))
// and is deleted when LinkedList is destroyed. See code comments above.
LinkedList<> elementObj(new ExampleObj);
마지막으로 LinkedList 체인에 나타날 수있는 모든 유형을 보유하려면 하나의 변형 클래스가 있어야합니다. 두 개의 서로 다른 LinkedList Variant 유형은 "next"포인터 유형 때문에 다시 작동하지 않습니다. 호환되지 않을 것입니다.
각주 : 유형 제약은 쉬운 해결책을 어떻게 방지합니까?링크 된 노드 "next"포인터 유형이 베어 메탈 템플리트 이름, 바로 가기가 아니라 템플릿 인수를 포함하여 실제로 자격이 있는지를 상상해보십시오. 컴파일러가 유형 컴플렉스를 판별하는 데 사용되는 유형 기호로 끝납니다.
다른 유형의 링크 된 목록을 만들려고하십니까? – Xeo
올바르게 이해하고 있는지 확인하기 위해 LinkedList을 가지고 있고 그 안에 Blah *를 넣고 LinkedList를 자동으로 소멸시키고 연결된 목록의 내용이 가리키는 모든 객체를 해제 할 수 있습니까? 이것은 수업이하지 말아야하는 것처럼 보입니다. 개체를 활성 상태로 유지하고 목록에 밀어 넣었 으면 목록이 삭제됩니다. 어쩌면 당신은 어떤 종류의 스마트 포인터를 찾고 있습니까? (부스트 스마트 포인터와 비슷합니다.) –
Corbin
@Xeo 예,하지만 유형 중 하나는 enums (정적)이고 다른 유형은 Things (동적)에 대한 포인터가됩니다. 구조가 이미 존재하며 템플릿으로 변환해도 작동 중입니다 – gardian06