У меня есть простой класс C++, который использует общие шаблоны для хранения и извлечения общих переменных. Сохранение их не проблема, но возврат универсальной переменной возвращает шестнадцатеричное значение.
Может ли кто-нибудь сказать мне, почему это происходит?
узел.h
#pragma once
#include <iostream>
template <typename T>
class Node {
private:
T data;
Node *next_node;
public:
Node(T data) {
this->data = data;
std::cout << "Node with data - " << this->data << " - has been created." << std::endl;
}
T get_data() {
return this->data;
}
void set_next_node(Node next) {
this->next_node = next;
}
Node get_next_node() {
return this->next_node;
}
};
main.cpp
#include <iostream>
#include "node.h"
int main() {
Node node = new Node("Hello World");
std::cout << "Node data: " << node.get_data() << std::endl;
return 0;
}
выход
gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ g++ main.cpp -o main
gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ ./main
Node with data - Hello World - has been created.
Node with data - 0x55ec552d3eb0 - has been created.
Node data: 0x55ec552d3eb0
как вы думаете, что такое T
? и очень связано с этим, почему вы используете new
?
@ChrisMM Что вы имеете в виду, что вывод не совпадает? Я обновил вопрос.
вам удалось скомпилировать Node x = new Node
, +1 за это. Это интересный случай максимальной путаницы, вызванной бессмысленным использованием new
.
Текст в нем отличается от вывода. Таким образом, они не могут быть связаны.
@ChrisMM компилируется, есть два разных экземпляра Node
@ 463035818_is_not_a_number, ты прав. Внимательнее надо было читать. Однако вывод по-прежнему не совпадает с кодом.
@ 463035818_is_not_a_number Вы правы. Удаление нового исправило это. Когда я должен использовать new
при запуске класса? (Я все еще изучаю C++, так что, пожалуйста, потерпите меня).
Первая строка кода OP в их main
эффективно делает это: Node node{ new Node("Hello World") };
. Таким образом, создаются два узла, один из которых имеет тип шаблона Node*
.
Ммм ... Я никогда не думал, что вывод аргумента шаблона класса может иметь эту конкретную ошибку. C++ и его новые свойства становятся «лучше» с каждым днем.
Я не думаю, что дубликат подходит. В этом коде происходит гораздо больше. И адрес не из печати массива. Проголосовать за открытие
Как вы думаете, какое значение имеет T
для node
? std::string
? const char[12]
? На самом деле у вас есть Node<Node<const char*>*>
.
Вау, эта строка Node x = new Node
очень запутанная, я думаю, она заслуживает фактического ответа.
«Эта строка» — результат того, что кто-то, кто знает C# или Java, пытается изучить C++ и предполагает, что C++ работает так же. Это не так.
Самое смешное, что можно написать еще один конструктор и руководство по дедукции, которое заставит Node x = new Node
делать «правильные вещи». Наконец-то можно написать это на C++. Ууууу. Я не думаю, что это то, что они имели в виду, когда представляли ctad :D
"когда я должен использовать новый" - никогда. (Вы будете сейчас, когда вам нужно, но никогда не является хорошим приближением)
Без CTAD строка в main выглядит так:
Node<Node<const char*>*> node = new Node<const char*>("Hello World");
Я не уверен, что вы на самом деле хотели, но я уверен, что это не это.
Напечатанный адрес является значением Node<const char*>*
члена Node<Node<const char*>*>
.
Проблема, с которой вы столкнулись, заключается в том, что вы используете new
для создания узла, но затем пытаетесь присвоить указатель, возвращаемый переменной Node
без указателя.
Эта строка является проблемой:
Node node = new Node("Hello World");
Что это делает, так это сначала создает безымянный объект Node
с типом шаблона const char *
; затем, используя указатель на этот новый объект для инициализации вашей переменной node
, вы создаете второй объект Node
с выведенным типом шаблона Node*
. Строки cout
, показывающие шестнадцатеричные значения, правильно отображают значение адреса, хранящееся во второй переменной с именем Node
.
Вы можете обойти это несколькими способами. Проще всего не использовать оператор new
:
Node node{ "Hello World" }; // Construct object directly
Другой способ — продолжить использовать вызов new
, но затем сделать node
указателем:
int main()
{
Node<const char*>* node = new Node("Hello World"); // Or auto node = new Node("Hello World");
std::cout << "Node data: " << node->get_data() << std::endl; // Now we need "->" instead of the "."
delete node;
return 0;
}
Первая строка кода в вашей функции main
фактически делает следующее:
Node node{ new Node("Hello World") };
Таким образом, создаются два узла, один из которых имеет тип шаблона Node<const char*>*
. Или, другими словами, ваша первая строка эквивалентна следующей с явными типами шаблонов:
Node< Node<const char*>* > node = new Node<const char*>("Hello World");
Также обратите внимание, что оператор =
здесь не присваивание, а инициализация; вот почему вызывается конструктор.
Спасибо, что помогли мне решить проблему и объяснили мне, что я делаю неправильно!
Код, который вы показываете, и вывод, который вы показываете, не совпадают. Ваш код даже не скомпилируется Пожалуйста, предоставьте минимальный воспроизводимый пример