Подтвердить что ты не робот

Указатель класса шаблона С++

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

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

Не удалось скомпилировать, я должен объявить указатель как

Node<int>* ptr;

Почему мне нужно указывать тип при объявлении указателя, который еще не создал класс, почему компилятор должен знать, на какой тип он будет указывать. И не представляется возможным создать общий указатель и решить, после какого типа я хочу его назначить.

4b9b3361

Ответ 1

Templating разрешает типы во время компиляции. Когда вы назначаете ему новый объект Node<int>, указатель должен знать во время компиляции, какой именно тип.

Node<int> и Node<std::vector> могут быть очень разными в двоичных файлах (двоичный макет вашего объекта полностью изменяется в соответствии с параметром шаблона), поэтому нет смысла иметь неразрешенный тип указателя для шаблона.

Сначала вы должны определить общий родительский класс для своих узлов:

class NodeBase
{ ... }

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

NodeBase* ptr;

Ответ 2

Простой ответ заключается в том, что С++ использует (справедливо) статический тип strick проверка. Node<int> - полностью не связанный тип с Node<double>, и когда компилятор видит ptr->doSomething(), он должен знать, для вызова Node<int>::doSomething() или Node<double>::doSomething().

Если вам нужна какая-то динамическая общность, где фактический тип ptr будет указывать на то, что будет известен только во время выполнения, вам нужно определить базовый класс и извлечь из этого. (Это довольно распространенный Идиома для шаблона класса, которая выводится из базы без шаблонов, точно так что общность в указателях может быть разрешена во время выполнения.)

Ответ 3

Почему я должен указать тип при объявлении указателя, который еще не создал класс, почему компилятор должен знать, на какой тип он будет указывать.

Есть много вещей, которые вам разрешено делать с указателем, просто перечисляя очень мало:

  • вызов одной из многих функций, основанных на типе указателя
  • от него (в предположении, что он указывает на первые элементы в смежном массиве таких объектов)
  • возьмите размер объекта с указателем.
  • передать его в шаблон, где тип указателя является параметром

Чтобы компилятор мог генерировать код для эффективного использования, ему необходимо знать тип указателя. Если он отложил решения до тех пор, пока не увидит тип указателя, тогда он должен будет либо:

  • скомпилируйте эффективный код для каждого возможного типа, который позже может указывать указатель (создание сильно раздутой программы) или
  • создайте неэффективный код, который может обрабатывать все возможные типы с помощью наихудшего пессимистического неуклюжего поведения или
  • вставьте копию самого себя (компилятора) в вашу программу на С++, чтобы она могла завершить работу, когда она получила необходимую информацию, - что сделало бы любую тривиальную программу огромной (и медленной)

И не представляется возможным создать общий указатель и решить, после какого типа я хочу его назначить.

Вид... у вас есть много вариантов:

  • используйте void*, но прежде чем он сможет осмысленно работать с заостренным типом, вам нужно вручную вернуть его к этому типу: в вашем случае это означает запись где-то, что было тогда, с отдельным кодом для любой возможности
  • используйте boost::any<> - в значительной степени похожий на void*, но с безопасностью, встроенной в
  • use boost::variant<> - гораздо безопаснее и удобнее, но при создании указателя необходимо указать возможные типы указаний,
  • используйте полиморфное семейство объектов времени выполнения и виртуальную диспетчерскую обработку... это классическое объектно-ориентированное программирование... у вас есть указатель на "абстрактный" Node, который объявляет общие функции и данные членов, которые вы будете использовать для работать с любым типом node, то шаблонный Node класс проистекает из этого абстрактного Node и реализует специфические для типов версии функций. Затем их вызывают через указатель на базовый класс с помощью virtual функций.

Ответ 4

Всякий раз, когда вы создаете какой-либо объект (включая указатели) в С++, должен быть известен полный тип объекта. В вашем коде нет такого типа Node, поэтому вы не можете создавать экземпляры указателей на него. Вам нужно переосмыслить, как вы разрабатываете и записываете свой код.

Ответ 5

Как заметил Нил Баттерворт и Люк Дантон, вы не можете иметь указатель типа Node *, потому что Node не является типом. Это шаблон. Да, Node - это шаблон класса, но этот класс здесь просто определяет тип шаблона. Один из способов взглянуть на это: так же, как классы и экземпляры классов - это разные вещи, так же как и шаблоны и экземпляры шаблонов. Именно эти экземпляры шаблонов, такие как Node, являются классами. Шаблон класса - это другой вид зверя.