无法将指针分配给模板派生的 class

Can't assign a pointer to a template-derived class

我正在制作模板 class。这并不重要,但我的目标是一个列表 class,它将使用一些静态成员来维护 class 对象的链表。每个不同的 class 都有自己的列表。不仅如此,每个 class 都有一个编译时分配的对象可用实例池,而不是从公共堆中提取它们。我正在开发资源有限的裸机系统。避免使用堆的部分原因是为了避免在嵌入式系统中长时间 运行 出现碎片。另一部分是决定论。我不希望分配的 ObjectA 数量与分配的 ObjectB 数量相互作用,我希望每个对象的数量都可预测。在实时嵌入式系统中,可预测性和一致性通常比原始性能更重要。我在 C 中一直这样做,但我正在努力在保持 C 效率的同时升级到 C++。

这是一个简化的示例,它说明了我的 C++ 问题的症结所在。

template <class T>
class ListOf<T>
{
public:
  static ListOf<T> *method();
};

我希望能够派生出具有 ListOf 的所有方法和属性的 classes 模板 class 加上额外的“有效负载”属性。我以为我能做到 通过 subclassing 一个从模板派生的 class:

class Something
{
// nothing here.  This is only used to let me give a unique name to my derived class.
};

class ListOfSomething : public ListOf<Something>
{
  int payloadProperty; // specific to the derived class
};

我希望能够做到这一点:

ListOfSomething *ptr;
ptr = ListOfSomething::method();

但是编译器告诉我不能将 ListOf* 分配给 ListOfSomething* 我想我能理解。我要求将基 class 指针转换为派生 class 指针。我可以用这样的静态转换来解决它

ListOfSomething *ptr;
ptr = static_cast<ListOfSomething *>ListOfSomething::method();

但这看起来很笨拙。似乎模板概念的重点就是做这样的事情。

也许我的整个方法是错误的。参考我更广泛的目标,而不是具体的转换问题,我知道我可以将指向 T 的指针添加到我的模板 class:

template <class T>
class ListOf<T>
{
public:
  ListOf<T> *method();
  T *payload;
};

class Something
{
int payloadProperty;
};

class ListOfSomething : public ListOf<Something>
{
};

但我试图避免一定程度的间接性。使用这种方法,每次我想访问它时,我都必须单独分配有效负载并取消引用一个指针。我正在寻找一些方法来扩展 ListOf class,这相当于向 class 添加更多成员,有效地创建

class ListOfSomething
{
public:
  ListOfSomething *method();
  T payload;
};

但以某种方式封装了分配列表机制。重新分配、遍历等以实现可重用性。

我们所做的不是从列表基 class 派生 ListOfSomething。我们将使 ListOfSomething 成为单例并有一个通用列表 class.

class ListOfSomething
{
  public:
    
   static ListOfSomething& instance()
   {
     static ListOfSomething los;
     return los;
   }

   // Obtain a reference to the list.
   ListOf<Something>& get_list() { return the_list; }

  private: 
    // Hide the constructor to force the use of the singleton instance.
    ListOfSomething() {}

    // The actual list of objects.
    ListOf<Something> the_list;

    // Add your properties.
    
};

另一种方法是将派生 class 的类型传递给基础 class。它有点混乱,但会起作用。这个经常用在.

template <class T, class L>
class ListOf<T>
{
  public:
    // I would advice to return a reference not a pointer.
    static L& method() 
    {
      static L list;
      return L;
    }

  private:
    // Hide the constructor.
    ListOf();
    ~ListOf();
};

接下来在你派生的class:

class ListOfSomething : public ListOf<Something, ListOfSomething>
{
  // To allow the construction of this object with private constructor in the base class.
  friend class ListOf<Something, ListOfSomething>;

  public: 
    // Add your public functions here.

  private:
    // Hide the constructor and destructor.
    ListOfSomething();
    ~ListOfSomething();
};

正如 Bart 所解释的,这里的技巧是将派生的 class 的名称作为模板参数传递。这是 class 的最终形式,它按最初的要求工作:

template <class T>
class ListOf<T>
{
public:
  static T *method();
};

然后你像这样调用它

class ListOfSomething : public ListOf<ListOfSomething>
{
public:
  int payload;
};

因此,编译器满意:

ListOfSomething *ptr;
ptr = ListOfSomething::method();