C ++ странная ошибка компиляции: ошибка: изменяет значение «объекта» из класса «объект» - PullRequest
8 голосов
/ 12 ноября 2008

Я даже не знаю, куда пойти с этим. Google не был очень полезным. Как с моим предыдущим вопросом. Я использую Ctrl + R TextMate для компиляции проекта.

game.h: 16: ошибка: объявление ‘Player * HalfSet :: Player () const’

Players.h: 11: ошибка: меняет значение «Player» с «класса Player»

game.h: 21: ошибка: «Игрок» не относится к типу

файл player.h (частично)

#ifndef PLAYERS_H
#define PLAYERS_H
using namespace std;

#include <string>
#include <vector>
#include <istream>
#include <iomanip>
#include "generics.h"

class Player{ //Line 11
public:
    //getters
    long Id() const;
    string FirstName() const;
    string LastName() const;
    string Country() const;
    //setters
    void setId(long id);
    void setFirstName(string s);
    void setLastName(string s);
    void setCountry(string s);
    //serializing functions
    void display(ostream &out);
    void read(istream &in);
    void write(ostream &out);
    //Initalizers
    Player();
    Player(istream &in);
    Player(string firstName, string lastName);
    Player(string firstName, string lastName, string country);
    Player(long id, string firstName, string lastName, string country);
    ~Player();
private:
    long _id;
    string _firstName;
    string _lastName;
    string _country;
};

файл game.h (частично)

#ifndef GAME_H
#define GAME_H

#include "generics.h"
#include "players.h"
#include <string>
#include <vector>
#include <istream>
#include <iomanip>

using namespace std;

class HalfSet{
public:
    //getters
    Player* Player() const; //Line 16
    int GamesWon() const;
    int TotalPoints() const;
    int Errors() const;
    //setters
    void setPlayer(Player* p);
    void setGamesWon(int games);
    void setTotalPoints(int points);
    void setErrors(int errors);
    //Serialization
    void display(ostream &out) const;
    void read(istream &in) const;
    void write(ostream &out) const;
    //Initalizers
    HalfSet();
    ~HalfSet();
private:
    Player* _player;
    int _gamesWon;
    int _points;
    int _errors;
};

Что здесь происходит?

Ответы [ 3 ]

16 голосов
/ 12 ноября 2008

В C ++ вы не можете называть функцию тем же именем, что и класс / struct / typedef. У вас есть класс с именем «Player», и поэтому в классе HalfSet есть функция с именем «Player» («Player * Player ()»). Вам нужно переименовать один из них (возможно, изменив функцию HalfSet's Player () на getPlayer () или что-то подобное).

8 голосов
/ 12 ноября 2008

Ваша проблема в том, что имена ищутся в областях. В объявлении HalfSet :: setPlayer (Player *) необходимо найти безусловное имя Player. Первая попытка - это класс HalfSet. В этой области поиск Player находит функцию HalfSet :: Player, а не глобальный class :: Player.

Решение состоит в том, чтобы использовать полное имя :: Player. Это сообщает компилятору, какую область видимости использовать для поиска (global), что, в свою очередь, означает, что HalfSet :: Player даже не рассматривается.

5 голосов
/ 02 ноября 2014

Текущий ответ на этот вопрос просто неверный, он говорит:

В C ++ нельзя называть функцию тем же именем, что и класс / struct / typedef

Допускается скрытие имени класса функцией, если мы перейдем к черновому стандарту Pre C ++ 11 раздел 3.3.7 Скрытие имени В нем говорится:

Имя класса (9.1) или имя перечисления (7.2) можно скрыть по имени объекта, функции или перечислителя, объявленного в той же области видимости. Если имя класса или перечисления и объект, функция или перечислитель объявлены в той же области (в любом порядке) с тем же именем, имя класса или перечисления скрыто везде, где объект, функция или имя перечислителя видно.

Так что тот факт, что у вас есть функция и класс с именем Player, не является проблемой, фактически следующий код действителен:

class Player
{
} ;

Player* Player() ;

и мы можем использовать разработанный спецификатор типа , чтобы скрыть тип класса.

Насколько я могу судить, это нарушает раздел 3.3.6 Область действия класса Абзац 2, в котором говорится:

Имя N, используемое в классе S, должно ссылаться на то же объявление в его контекст и при переоценке в завершенном объеме S. Нет Диагностика необходима для нарушения этого правила.

Таким образом, в этом случае Player меняет значение с класс на функцию , мне не ясно, было ли это так строго, но я вижу, как это можно прочитать сюда. Похоже, что это сообщение gcc использует, когда обнаруживает это нарушение, как мы видим из аналогичного вопроса .

Использование разработанного спецификатора типа предотвращает изменение значения:

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