Вопрос:
Я новичок в c++, и у меня возникают трудности с конструктором и классами. Итак, вот мой заголовочный файл:
#pragma once #include <string> using namespace std; class test { private: string name; int number; public: test(); test(string i,int b); };
Это файл cpp:
#include «test.h» #include <string> using namespace std; test::test(){} test::test(string i,int b){ this->name=i; this->number=b; }
теперь, когда я пытаюсь позвонить
test t=new test(«rrr»,8);
Я получаю:
1 IntelliSense: no suitable constructor exists to convert from «test *» to «test»
Итак, что происходит с классами, имеющими * в их имени (например, классы без .cpp файла не имеют asterix, все остальные)? И что я делаю неправильно?
Лучший ответ:
Я предполагаю, что вы работаете на фоне Java/С#. t здесь не является ссылочным типом, это тип значения. new возвращает указатель на объект. Поэтому вам нужно следующее:
test t = test(«rrr», 8); test t(«rrr», 8); test *t = new test(«rrr», 8);
Если вы еще не знакомы с указателями, то определенно не используйте последний! Но понимание семантики указателей довольно критично; Я рекомендую прочитать соответствующие главы в учебнике…
Ответ №1
Итак, что происходит с классами, имеющими “*” в их имени (например, классы без .cpp файла не имеют asterix, все остальные)???
Вам определенно нужно узнать о указателях. test * и test – два совершенно разных типа в С++. Здесь две переменные с этими типами:
test t; test* p;
Здесь t имеет тип test и p как тип test*. Мы описываем test* как “указатель на test“.
Вы можете часто думать о том, что указатель является адресом памяти объекта. Поэтому в p, так как это указатель, мы можем сохранить адрес памяти t, который является test. Чтобы получить адрес объекта, мы используем унарный оператор &, например:
test t; test* p = &t;
Обратите внимание, что t является объектом test. Вам не нужно было говорить new test(). Здесь С++ отличается от других языков, которые вы могли использовать, например С# и Java. В приведенном выше коде С++ t является объектом test.
Однако вы можете создавать объекты с помощью new test(), так какая разница?
test t; создает объект test с автоматическим временем хранения. Это означает, что он уничтожается в конце его области (часто функция объявляется внутри).
new test() создает объект test с динамической продолжительностью хранения. Это означает, что вам нужно уничтожить объект вручную, иначе у вас будет утечка памяти. Это выражение возвращает указатель, и вы можете инициализировать его с помощью объекта-указателя:
test* p = new test();
Теперь посмотрим на вашу проблему:
test t=new test(«rrr»,8);
Теперь мы знаем, что new test(«rrr», 8) возвращает указатель на test (a test*). Однако вы пытаетесь присвоить его объекту test. Вы просто не можете этого сделать. Один из них – адрес, а другой – test. Следовательно, компилятор говорит “нет подходящего конструктора для преобразования из test * в test“. Теперь имеет смысл, не так ли?
Вместо этого вы должны использовать автоматическую продолжительность хранения. Используйте new, если вам действительно нужно. Так просто:
test t(«rrr», 8); Ответ №2test t=new test(«rrr»,8);
должен быть
// v test* t=new test(«rrr»,8);
Итак, что происходит с классами, имеющими “*” в их имени
* используется для указания указателя, это не имя класса. Но это очень важная тема, поэтому вы должны позаботиться об этом.
Ответ №3
* не является частью имени, это модификатор, обозначающий, что объект является указателем. Указатель – это адрес размещения переменной в каком-либо месте в памяти, где хранится фактический объект. Некоторые основы:
int i = 5; int * pI = &i;
int * pI означает, что вы хотите объявить указатель для размещения в памяти, где хранится int. &i означает, что вы хотите получить указатель на переменную. Итак, теперь pI хранит адрес в памяти, где я хранится. Теперь вы можете разыменовать указатель – получить значение указателя:
int j = *pI;
Теперь вы говорите компилятору, что он должен перейти к адресу, на который указывает pI, и получить его содержимое (поскольку pI является указателем на int, компилятор будет считать, что там есть int).
Теперь вернемся к вашему примеру. Оператор new динамически выделяет память для объекта, поэтому:
new test(«rrr», 8);
приводит к распределению памяти для тестового класса, вызывая его конструктор с параметрами “rrr” и 8 и возвращая указатель на выделенную память. Вот почему вы не можете назначить его переменной test: новый оператор в этом случае возвращает test *.
Попробуйте этот код:
test * t = new test(«rrr», 8); Ответ №4
Вы не указали t как указатель:
test* t=new test(«rrr»,8);
Или просто
test t = test(«rrr»,8); Ответ №5T* t = new T; // ^^^
Когда в этой конструкции объекта используется новый, он обозначает создание указателя. Что происходит, так это динамическое распределение памяти, которое, я уверен, вы не хотели делать. Скорее, типичная структура объектов, построенных на стеке, выполняется просто так:
T t;
Даже если вы планировали создать указатель и выделили память, вы сделали это неправильно. Указатель создается с символом *, которого вам не хватает в коде. Во-вторых, когда вы закончите использовать созданную память, вы должны запомнить delete/delete[] ваш код. delete[] используется для динамически распределенных массивов. Так вот как он будет искать ваш указатель:
delete t;