无法将指针分配给模板派生的 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();
我正在制作模板 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();