可以容纳多种类型数据的数据结构

时间:2010-07-08 03:08:10

标签: c++ data-structures

就像标题所说,我正在寻找某种数据结构,这将允许我将任何类型的类存储到我当时需要的类中。例如:

Foo *foo = new Foo();
Bar *bar = new Bar();
someContainer.push_back( foo );
someContainer.push_back( bar );
someContainer.access( 0 )->doFooStuff();
someContainer.access( 1 )->doBarStuff();

理想情况下,正如我在那里展示的那样,它还允许我访问内容并使用它们的功能/等 我想要其中一个,因为我正在尝试创建一个“隐形”内存管理系统,只需要一个类来继承我的内存管理器类,一切都会自动运行。
以下是我希望代码看起来像的示例:

template< class T >
class MemoryManaged
{
   MemoryManaged()
   {
      container.push_back( this );
   }
   void *operator new()
   {
       // new would probably be overloaded for reference counting etc.
   }
   void operator delete( void *object )
   {
       // delete would most definitely overloaded
   }
   T &operator=( T &other )
   {
      // = overloaded for reference counting and pointer management
   }

   static SomeContainer container;
}

class SomeClass : public MemoryManaged< SomeClass >
{
   // some kind of stuff for the class to work
};
class AnotherClass : public MemoryManaged< AnotherClass >
{
   // more stuff!
};

我希望我的代码有助于明确我想要做什么。如果有人知道某种已经构建的数据结构可以让我这样做,那就太棒了。否则,我目前正在构建某种使用模板化节点的链表类的抖动僵尸,以便将任何类型的类链接到任何其他类型的类。我仍然不知道我是如何让它继续工作的,而且我希望能够省去血液,汗水和眼泪(和头发),以便弄清楚如何使它发挥作用。

4 个答案:

答案 0 :(得分:4)

为所有多种类型提供公共基类。让数据结构保持基类类型的指针。

答案 1 :(得分:3)

答案 2 :(得分:1)

模板专业化和双重调度的混合会有帮助吗?像这样:

class IContainable;
class Operation
{
public:
   template<class ElementType> void Process(ElementType* pEl) {
      // default is an unrecognized type, so do nothing
   }
};

class IContainable
{
public:
    virtual void OperateOn(Operation* pOperation) = 0;
};


class Foo : public IContainable
{
public:
    int GetFooCount() { return 1; }
    virtual void OperateOn(Operation* pOperation);
};

// specialization of the operation for Foo's
template <> void Operation::Process<Foo>(Foo* pFoo)
{
     std::cout << pFoo->GetFooCount() << std::endl; 
}

void Foo::OperateOn(Operation* pOperation)
{
   pOperation->Process(this);
}

int main()
{
    typedef std::vector<IContainable*> ElementVector; 
    ElementVector elements;
    // configure elements;
    Operation oper;
    for(ElementVector::iterator it = elements.begin(); 
         it != elements.end(); it++)
    {
        (*it)->OperateOn(&oper);
    }
}

如果在容器上元素的操作的编译时不知道容器中的类型列表,或者它们是在未编译在一起的模块之间分布的,那么您可以改为使用dynamic_cast。您将使用名为“HandleFoo”的纯虚方法定义一个“IFooHandler”类,该方法采用foo指针。你将Operation :: Process虚拟化,让你的操作类派生自Operation和IFooHandler,并在HandleFoo()中实现操作。你的Foo :: OperateOn方法将是dynamic_cast(pOperation),如果结果是非null,它将在动态强制转换得到的IFooHandler指针上调用HandleFoo()。否则,您将调用通用的Operation :: Process,它将具有一些非类型特定的行为。

答案 3 :(得分:0)

使用std::vector<T*>应该有效。实际上,将为MemoryManaged的每个实例创建一个新类。这意味着MemoryManaged<Foo>MemoryManaged<Bar>将是完全不同的类型。因此,静态成员container对于这两个类并不常见。就好像你有以下两个类:

class MemoryManagedFoo
{
    MemoryManagedFoo()
    {
        //Here, you know that 'this' is a Foo*
        container.push_back(this); //ok, we add 'this' to a container of Foo*
    }

    static std::vector<Foo*> container;
};

class MemoryManagedBar
{
    MemoryManagedBar()
    {
        //Here, you know that 'this' is a Bar*
        container.push_back(this); //ok, we add 'this' to a container of Bar*
    }

    static std::vector<Bar*> container;
};

如您所见,两个实例不共享静态成员。

当然,此解决方案假定使用CRTP始终使用MemoryManaged,如您在问题中所述。换句话说,这段代码将起作用:

class Foo : public MemoryManaged<Foo> { };

但不是这一个:

class Foo : public MemoryManaged<Bar> 
{
    // Here, 'container' is a 'vector<Bar*>' and 'this' is a Foo * --> problem
};