Ошибка "request for member '...' in '...' which is of non-class type" в C++
Причина ошибки
Ошибка возникает из-за того, что ptr — это указатель на объект Student, а не сам объект. Когда вы пишете ptr.name, компилятор пытается найти поле name в типе Student* (указателе), а не в Student. Указатель — это не класс, у него нет членов, поэтому компилятор сообщает: "запрос члена у типа, не являющегося классом".
Решение: используйте оператор разыменования или стрелку
В C++ для доступа к членам объекта через указатель есть два способа:
1. Оператор разыменования * и точка .
Сначала разыменуйте указатель (получите сам объект), затем используйте точку:
(*ptr).name = "Ivan";
Скобки обязательны, потому что оператор точки имеет более высокий приоритет, чем оператор разыменования.
2. Оператор стрелки -> (рекомендуемый способ)
Это синтаксический сахар для предыдущего варианта. Стрелка делает то же самое — разыменовывает указатель и обращается к члену:
ptr->name = "Ivan";
Исправленный код
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
string name;
int age;
void printInfo() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
Student* ptr = new Student();
// Правильный способ через стрелку
ptr->name = "Ivan";
ptr->age = 20;
// Или через разыменование: (*ptr).name = "Ivan";
ptr->printInfo(); // тоже через стрелку
delete ptr;
return 0;
}
Важное замечание: когда точка, а когда стрелка
- Точка (
.) — используется, когда у вас есть сам объект (не указатель):Student s; s.name = "Ivan"; - Стрелка (
->) — используется, когда у вас есть указатель на объект:Student* p = new Student(); p->name = "Ivan";
Дополнительный пример для закрепления
Student obj; // объект на стеке
obj.name = "Petr"; // точка
Student* pObj = &obj; // указатель на объект
pObj->name = "Petr"; // стрелка
// То же самое через разыменование:
(*pObj).name = "Petr"; // разыменование + точка
Запомните: если переменная объявлена как Тип* — используйте ->. Если как Тип — используйте .. Это универсальное правило для C++.
Альтернативный взгляд: работа с объектами на стеке
Если вы только начинаете изучать C++, часто проще избегать ручного управления памятью через new и delete. Вместо указателя можно создать объект непосредственно на стеке:
int main() {
Student student; // объект на стеке, не указатель
student.name = "Ivan";
student.age = 20;
student.printInfo();
// delete не нужен — объект уничтожится автоматически
return 0;
}
В этом случае вы используете точку (.) для доступа к членам, и ошибка не возникает. Такой подход проще для понимания и безопаснее — вы не рискуете забыть вызвать delete или получить утечку памяти.
Указатели с new стоит использовать, когда нужно динамическое выделение (например, для полиморфизма, массивов переменного размера или объектов, живущих дольше области видимости). Для учебных примеров на начальном этапе лучше обходиться стековыми объектами.
Ответов пока нет.
Войдите чтобы оставить ответ