C ++ - метод, который принимает указатель, но получает int - PullRequest
3 голосов
/ 31 марта 2012

Мне интересно, как бы я справился с вызовом функции, когда целое число передается в функцию, которая принимает указатель? В моем случае hasPlayedInTeam () принимает указатель на Team, однако получил int. Это приводит к зависанию Q_ASSERT.

Кроме того, моя проблема также известна как нулевой указатель? Мой профессор несколько раз использовал этот термин в лекции, но я не уверен, что он имел в виду.

//main.cpp
Person p1("Jack", 22, "UCLA");
Q_ASSERT(p1.hasPlayedInTeam(0) == false);


//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
  bool temp = false;
  foreach (Team* team, teamList) {
    if (team->getName() == pTeam->getName() {
      temp = true;
    }
  }
  return temp;
}

Ответы [ 6 ]

7 голосов
/ 31 марта 2012

В вашем звонке:

p1.hasPlayedInTeam(0)

целочисленный литерал 0 преобразуется в указатель NULL. Таким образом, вы на самом деле не «получаете» целое число; если вы передаете целое число, компилятор может автоматически привести его к нулевому указателю (учитывая определение для NULL).

Я думаю, что вы можете исправить определение hasPlayedInTeam, либо заявив, что его аргумент не равен NULL, либо вернув значение по умолчанию, когда передается NULL:

//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
    assert(pTeam!=NULL); //-- in this case, your program will assert and halt

или

//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
    if (pTeam == NULL)
         return false; //-- in this case, your program will not assert and continue with a sensible (it actually depends on how you define "sensible") return value
2 голосов
/ 31 марта 2012

Да, похоже, ваша проблема - нулевой указатель.Нулевой указатель означает, что у вас есть указатель, который на самом деле ни на что не указывает:

Team* team = NULL;

Бывает, что в C ++ NULL есть макрос для целого числа 0. Stroustrup имеет someкомментарии , который он предпочитает использовать в коде.

1 голос
/ 31 марта 2012

В C ++ есть NULL, который определяется как 0 (в каком-то стандартном заголовочном файле cstddef, я думаю), так что да, целое число, которое вы передаете, является нулевым указателем.0 - это единственное (насколько мне известно) целое число, которое автоматически (неявно) будет преобразовано в указатель любого необходимого типа.

На практике я думаю, что большинство людей предпочитают использовать NULLвместо 0 для нулевого указателя.

Я не уверен, почему он зависает, однако разыменование указателя NULL (в вашем выражении pTeam->getName()) должно вызвать сбой программы, если вы передадитеэто NULL, а не просто зависание.

1 голос
/ 31 марта 2012

Да, я думаю, что в этой ситуации вы имеете в виду нулевой указатель.

Чтобы обработать случай, когда передается int, вы можете перегрузить функцию и заставить ее вести себя так, как вы хотите, когда передается int.

1 голос
/ 31 марта 2012

Функция hasPlayedInTeam () ищет аргумент типа «Команда», в то время как вы передаете аргумент типа «целое число», который является неправильным ....

0 голосов
/ 31 марта 2012

К сожалению, литерал нулевого указателя является одной из запутанных частей языка. Позвольте мне повторить:

  1. Для любого типа существует понятие «указатель на этот тип». Например, вы можете иметь целые числа и указатель на целые числа (int x; int *y;), удваивать и указатель на двойные (double x; double *y;), Персона и указатель на Персона (Person x,*y;). Если X является типом, то «указатель на X» является самим типом , и, следовательно, вы даже можете найти указатели на указатели на целые числа (int **x;) или указатели на указатели на указатели на символы (char ***x;).

  2. Для любого типа указателя есть значение null pointer . Это значение, которое на самом деле не указывает на объект, поэтому попытка разыменовать его является ошибкой («разыменование» указателя означает чтение или запись объекта, на который указывает указатель). Обратите внимание, что язык C ++ не гарантирует, что вы получите сообщение или сбой при использовании нулевого указателя для попытки добраться до несуществующего заостренного объекта, но только то, что вы не должны делать это в программе, потому что последствия непредсказуемы. Язык просто предполагает, что вы не собираетесь делать такого рода ошибки.

  3. Как нулевой указатель выражается в программе? Здесь начинается сложная часть. По непонятным причинам язык C ++ использует странное правило: если вы получаете любое постоянное целочисленное выражение со значением ноль , то это можно (если необходимо) считать нулевым указателем для любого типа.

Последнее правило чрезвычайно странное и нелогичное, например, означает, что

char *x = 0;     // x is a pointer to char with the null pointer value (ok)

char *y = (1-1); // exactly the same (what??)

char *z = !!    !!  !!    !!  !!       !!  
          !!!   !!  !!    !!  !!       !!
          !!!!  !!  !!    !!  !!       !!
          !! !! !!  !!    !!  !!       !!
          !!  !!!!  !!    !!  !!       !!
          !!   !!!  !!    !!  !!       !!
          !!    !!   !!!!!!   !!!!!!!  !!!!!!1; // Same again (!)

и это верно для любого типа указателя.

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

Очевидно, что Страуструп также нашел забавную вещь вместо того, чтобы быть отвратительной, какой она должна быть (последний пример с текстом «NULL», написанным с нечетным числом отрицаний, представлен в книге «Язык программирования C ++»).

Также обратите внимание, что в стандартных заголовках определен символ NULL, который обеспечивает правильное определение значения нулевого указателя для любого типа. В «C» допустимое определение могло бы быть (void *)0, но это недопустимо в C ++, потому что указатели void не могут быть неявно преобразованы в другие типы указателей, как они делают в «C».

Обратите внимание, что в литературе вы можете найти термин NUL (только один L), но это символ ASCII с кодом 0 (представлен в C / C ++ с '\0') и является логически отличная вещь от указателя или целого числа.

К сожалению, в C ++ символы тоже являются целыми числами, и поэтому, например, '\0' является допустимым значением нулевого указателя, то же самое относится и к ('A'-'A') (это целочисленные константные выражения с нулевым значением).

C ++ 11 увеличивает сложность этих и без того сомнительных правил с std::nullptr_t и nullptr. Я не могу объяснить эти правила, потому что сам не понял их (и еще не уверен на 100%, что хочу их понять).

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