模板类指针 c++宣言

发布于 2024-11-15 14:32:18 字数 281 浏览 4 评论 0原文

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

int main
{
    Node* ptr;
    ptr = new Node<int>;
}

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

Node<int>* ptr;

为什么在声明指针时必须指定类型我还没有创建该类,为什么编译器必须知道它将指向什么类型。是否不可能创建一个通用指针并随后决定我要分配给它的类型。

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

int main
{
    Node* ptr;
    ptr = new Node<int>;
}

Will fail to compile I have to to declare the pointer as

Node<int>* ptr;

Why do I have to specify the type when declaring a pointer I haven't created the class yet, why does the compiler have to know what type it will be pointing to. And is it not possible to create a generic pointer and decide afterwards what type I want to assign it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

山人契 2024-11-22 14:32:18

模板化在编译时解析类型。当您将新的 Node 对象分配给它时,指针必须在编译时知道它到底是什么类型。

NodeNode 在二进制文件中可能非常不同(对象的二进制布局完全根据模板参数发生变化),因此它不会拥有指向模板的未解析的指针类型是没有任何意义的。

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

class NodeBase
{ ... }

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

NodeBase* ptr;

Templating resolves types at compile-time. When you assign the new Node<int> object to it, the pointer must know at compile-time what type exactly it is.

Node<int> and Node<std::vector> can be very different in the binaries (the binary layout of your object changes completely according the template parameter) so it doesn't make any sense to have an unresolved pointer type to a template.

You should define first a common parent class for your nodes:

class NodeBase
{ ... }

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

NodeBase* ptr;
朱染 2024-11-22 14:32:18

简单的答案是因为 C++ 使用(相当)严格的静态类型
检查。 Node 是与 Node 完全无关的类型,
当编译器看到 ptr->doSomething() 时,它必须知道是否
调用 Node::doSomething()Node::doSomething()

如果您确实需要某种动态通用性,那么
ptr 将指向的实际类型仅在运行时才知道,您需要
定义一个基类,并从中派生。 (这是一个相当常见的
准确地说,类模板从非模板基派生的习惯用法
以便可以在运行时解决指针的通用性。)

The simple answer is because C++ uses (fairly) strict static type
checking. Node<int> is a completely unrelated type to Node<double>,
and when the compiler sees ptr->doSomething(), it has to know whether
to call Node<int>::doSomething() or Node<double>::doSomething().

If you do need some sort of dynamic generality, where the
actual type ptr will point to will only be known at runtime, you need
to define a base class, and derive from that. (It's a fairly common
idiom for a class template to derive from a non-template base, precisely
so that the generality in the pointers can be resolved at runtime.)

美人骨 2024-11-22 14:32:18

为什么在声明指针时必须指定类型我还没有创建该类,为什么编译器必须知道它将指向什么类型。

您可以使用指针做很多事情,仅列出极少数:

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

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

  • 为指针以后可能采用的每种可能类型编译有效的代码(使程序变得非常臃肿),或者
  • 创建可以处理所有类型的低效代码。通过一些最坏情况的悲观笨拙行为来识别可能的类型,或者
  • 将其自身的副本(编译器)嵌入到您的 C++ 程序中,以便它可以在获得必要的信息时完成其工作 - 这将使每个琐碎的程序变得巨大(并且 慢的)

是否不可能创建一个通用指针并随后决定我要分配给它的类型。

有点......你有很多选择:

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

Why do I have to specify the type when declaring a pointer I haven't created the class yet, why does the compiler have to know what type it will be pointing to.

There are lots of things you're allowed to do with a pointer, just to list a very few:

  • call one of many functions based on the pointer's type
  • index from it (on the assumption that it points to the first elements in a contiguous array of such objects)
  • take the size of the pointed-to object
  • pass it to a template where the pointer-type is a parameter

For the compiler to generate code to do these efficiently, it needs to know the type of the pointer. If it defered the decisions until it saw the type of the pointer, then it would need to either:

  • compile efficient code for every possible type the pointer might later take (making a hugely bloated program), or
  • create inefficient code that can handle all the possible types through some worst-case pessimistic clumsy behaviours, or
  • embed a copy of itself (the compiler) into your C++ program so it can complete it's job when it's got the necessary information - that would make every trivial program huge (and slow)

And is it not possible to create a generic pointer and decide afterwards what type I want to assign it.

Kind of... you have many options:

  • use a void*, but before it can meaningfully operate on the pointed-to-type again you'll need to manually cast it back to that type: in your case that means recording somewhere what it was then having separate code for every possibility
  • use boost::any<> - pretty much like a void*, but with safety built in
  • use boost::variant<> - much safer and more convenient, but you have to list the possible pointed-to types when you create the pointer
  • use a runtime polymorphic family of objects and virtual dispatch... this is classic Object Oriented Programming... you have a pointer to an "abstract" Node that declares the shared functions and member data you'd use to operate on any particular type of node, then the templated Node class derives from that abstract Node and implements type-specific versions of the functions. These are then called via a pointer to the base class using virtual functions.
酒儿 2024-11-22 14:32:18

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

Whenever you create any kind of object (including pointers) in C++, the full type of the object must be known. There is no such type in your code as Node, so you can't create instances of pointers to it. You need to rethink how you are designing and writing your code.

止于盛夏 2024-11-22 14:32:18

正如 Neil Butterworth 和 Luc Danton 所指出的,您不能拥有 Node* 类型的指针,因为 Node 不是类型。它是一个模板。是的,Node 是一个类模板,但这里的 class 只是限定了模板的类型。一种看待它的方法是:正如类和类的实例是非常不同的东西一样,模板和模板实例化也是非常不同的。那些模板实例(例如 Node)就是类。类模板是另一种野兽。

As both Neil Butterworth and Luc Danton noted, you can't have a pointer of type Node* because Node is not a type. It is a template. Yes, Node is a class template, but that class here just qualifies the kind of template. One way to look at it: Just as classes and instances of classes are very different things, so too are templates and template instantiations. It is those template instantiations such as Node that are classes. The class template is some other kind of beast.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文