я могу использовать ЭТОТ указатель в классе друга? - PullRequest
1 голос
/ 15 марта 2012
#include <iostream>

using namespace std;

class Street;

class CrossStreet

{

        private:

             char m_chName;
             Street* m_acLoS;
             int m_nNoS;
             static int m_nCSid;
        public:
             CrossStreet()
             {
                  Init();
                  m_chName = m_nCSid;
             }
             CrossStreet(char chName)
             {
                  Init();
                  m_chName = chName;
             }

             /** Problem is here **/
             void AddStreet(Street* const cStreet)
             {
                  m_acLoS[++m_nNoS] = cStreet;
             }

             ~CrossStreet()
             {
                  delete[] m_acList;
             }

             void Init()
             {
                  m_nNoS = 0;
                  m_acLoS = 0;
                  m_nCSid++;
             }

             friend class Street;
};

class Street

{

         private:

              int m_nDistance;

         public:

              Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance)
              {
                   CreateStreet(cHead,cTail,nDistance);
              }

              void CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance)
              {
                   m_nDistance = nDistance;
                   cHead.AddStreet(Street* const THIS);
                   cTail.AddStreet(Street* const THIS);

              }

};

, когда я компилирую вышеприведенный код, эта ошибка выброса:

-->>invalid use of incomplete 'struct Street'
-->>forward declaration of 'struct Street'

функция AddStreet объекта 'CrossStreet' была вызвана для объекта 'Street', чтобы добавить 'ЭТОТ объект улицык переменной-члену объекта CrossStreet.Так что я думаю, что я могу использовать этот указатель в этом случае, но он не компилируется.

Ответы [ 3 ]

3 голосов
/ 15 марта 2012

Нет таких вещей, как указатель THIS.Хотя есть указатель this.Таким образом, ваш код в CreateStreet недействителен (и не только для этого).Правильный синтаксис:

cHead.AddStreet(this); // no cast needed

Проблема в AddStreet состоит в том, что вы определили m_acLoS как указатель на улицу.Таким образом, m_acLoS[x] имеет тип Street, а не Street*.Но вы не можете использовать Street объект там, так как у вас нет полного определения Street на тот момент.Вы можете использовать указатели на улицу только в CrossStreet.(Кроме того, вам не хватает выделения памяти для m_acLoS, поэтому, даже если вы могли бы использовать этот тип там, и если назначение было законным, это все равно было бы ошибкой).

В зависимости от того, что вы 'после этого std::vector<Street*> или std::list<Street*> или какой-либо другой контейнер может быть тем, что вы ищете, вместо того, чтобы неверный массив элементов.(Но учтите, что вы несете ответственность за управление временем жизни этих указателей.)

3 голосов
/ 15 марта 2012

Не имеет ничего общего с указателем this, это имеет отношение к предварительному объявлению.Вы говорите, что Street - это class в вашем предварительном объявлении, но оно не определяет его определение, поэтому попытка использовать его определение до его определения является ошибкой.

То есть спредварительная декларация:

class Street;

Вы можете сказать что-то вроде:

Street* pS
Street& rS

Поскольку для них не требуется определение улицы.Но как только вы используете его способом, который требует определения (назначения объекта Street), вам требуется полное определение.

// m_acLoS - это Street *, поэтому m_acLoS [...] ссылается нана улицу.m_acLoS [++ m_nNoS] = cStreet;

Похоже, вы действительно хотите, чтобы массив был массивом указателя на улицу вместо массива на улицу (и на самом деле вектор, вероятно, был бы лучше).

Но, в общем, поскольку у вас есть CrossStreet в зависимости от Street и Street в зависимости от CrossStreet, вы должны поместить объявления для каждого класса в свои собственные заголовочные файлы, а реализации в свои собственные файлы .cpp, таким образом,Файлы .cpp с исходным кодом могут #include включать оба полных объявления перед любым кодом, который их использует.

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

Несколько человек уже рассказали вам о проблеме.Это больше фокусируется на решении.Тот, который я обычно одобряю, отделяет реализацию класса от определения класса.Я бы перестроил код примерно так:

#include <iostream>

using namespace std;

class Street;

class CrossStreet {
    char m_chName;
    Street* m_acLoS;
    int m_nNoS;
    static int m_nCSid;
    void Init();
public:
    CrossStreet();
    CrossStreet(char chName);
    void AddStreet(Street* const cStreet);
    ~CrossStreet();
    friend class Street;
};

class Street {
    int m_nDistance;
public:
    Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance);
    void CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance);
};


CrossStreet::CrossStreet() {
    Init();
    m_chName = m_nCSid;
}

CrossStreet::CrossStreet(char chName) {
    Init();
    m_chName = chName;
}

void CrossStreet::AddStreet(Street* const cStreet) {
    m_acLoS[++m_nNoS] = cStreet;
}

CrossStreet::~CrossStreet() {
    delete[] m_acList;
}

CrossStreet::void Init() {
    m_nNoS = 0;
    m_acLoS = 0;
    m_nCSid++;
}

Street::Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance) {
    CreateStreet(cHead,cTail,nDistance);
}

void Street::CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance) {
    m_nDistance = nDistance;
    cHead.AddStreet(this);
    cTail.AddStreet(this);
}

Итак, основная идея здесь - это объявление класса, затем определения класса, а затем реализации функций-членов.Также обратите внимание, что я сделал CrossStreet::Init приватным, поскольку он, очевидно, должен использоваться только членами CrossStreet.

В качестве заключительного замечания, пожалуйста, ради Бога, выберите несколько приличных имен дляваши переменные.Единственное имя, которое вы использовали, даже наполовину значимое и читаемое, - m_nDistance.Такие вещи, как m_chName и m_acLos действительно ужасны.Они очень похожи на имена, которые я придумал, когда писал диатрибы о пороках венгерской нотации и об ужасном, нечитаемом беспорядке, который можно из этого извлечь.

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