模板类指针c ++声明

ran*_*nas 17 c++ templates pointers class declaration

template <typename T>
class Node
{...};

int main
{
    Node* ptr;
    ptr = new Node<int>;
}
Run Code Online (Sandbox Code Playgroud)

将无法编译我必须将指针声明为

Node<int>* ptr;
Run Code Online (Sandbox Code Playgroud)

为什么在声明指针时我必须指定类型我还没有创建类,为什么编译器必须知道它将指向哪种类型.并且不可能创建一个通用指针,然后决定我想要分配它的类型.

pro*_*ian 29

模板化在编译时解析类型.将新Node<int>对象分配给它时,指针必须在编译时知道它究竟是什么类型.

Node<int>并且Node<std::vector>二进制文件可能非常不同(对象的二进制布局完全根据模板参数更改),因此将未解析的指针类型指向模板没有任何意义.

您应该首先为节点定义一个公共父类:

class NodeBase
{ ... }

template<typename ValueT>
  class Node : public NodeBase
{
 ...
};

NodeBase* ptr;
Run Code Online (Sandbox Code Playgroud)

  • 我所做的就是在`Node <int>`和`Node <std :: vector>`周围添加反引号,将它们格式化为代码而不是文本.没有这种格式化,句子"节点和节点可能会非常不同",这是没有意义的. (8认同)
  • @Yola,我不确定你的意思是什么?问题不在于虚函数调用的开销.虚函数在某些情况下没有其他选择,即涉及运行时函数解析. (3认同)

Jam*_*nze 9

简单的答案是因为C++使用(相当)strick静态类型检查. Node<int>是一个完全不相关的类型Node<double>,当编译器看到时ptr->doSomething(),它必须知道是否调用Node<int>::doSomething()Node<double>::doSomething().

如果确实需要某种动态泛型,实际类型ptr将指向的只是在运行时才知道,您需要定义一个基类,并从中派生出来.(这是从非模板库派生的类模板的一个相当常见的习惯用法,正是这样才能在运行时解析指针中的通用性.)


Ton*_*roy 5

为什么在声明尚未创建类的指针时必须指定类型,为什么编译器必须知道它将指向的类型。

您可以使用指针做很多事情,仅列出一些:

  • 根据指针的类型调用许多函数之一
  • 从中索引(假设它指向此类对象的连续数组中的第一个元素)
  • 取指向对象的大小
  • 将其传递到指针类型为参数的模板

为了使编译器生成有效执行这些操作的代码,它需要知道指针的类型。如果将决定推迟到看到指针的类型,那么它将需要:

  • 为指针以后可能需要的每种可能的类型编译有效的代码(制作一个肿的程序),或者
  • 创建效率低下的代码,以通过一些最坏的悲观的笨拙行为来处理所有可能的类型,或者
  • 将自身(编译器)的副本嵌入到C ++程序中,以便在获得必要信息时可以完成其工作-这将使每个琐碎的程序变得庞大(且速度缓慢)

并且不可能创建通用指针并在事后确定我要分配的类型。

种类...您有很多选择:

  • 使用void*,但在再次有意义地对着指向类型进行操作之前,您需要手动将其强制转换为该类型:在您的情况下,这意味着将其记录在某个位置,然后针对每种可能性使用单独的代码
  • 使用boost::any<>-非常像void*,但是内置安全性
  • 使用boost::variant<>-更安全,更方便,但是在创建指针时必须列出可能的指向类型
  • 使用运行时多态对象和虚拟分派系列...这是经典的面向对象编程...您有一个指向“抽象”的指针,该抽象Node声明了用于对任何特定类型的对象进行操作的共享函数和成员数据节点,则模板化Node类从该抽象派生,Node并实现函数的特定于类型的版本。然后使用virtual函数通过指向基类的指针来调用它们。


小智 1

每当您在 C++ 中创建任何类型的对象(包括指针)时,都必须知道该对象的完整类型。您的代码中没有这样的类型Node,因此您无法创建指向它的指针的实例。您需要重新思考如何设计和编写代码。