2015-11-27 2 views
3

Я столкнулся с ошибкой ниже - когда я просто предоставляю определение класса первым, а затем объявляю его позже. Мое понимание было до тех пор, пока мы это делаем, поскольку я много раз выполнял определение функции, компилятор получает его, но, похоже, мое понимание ошибочно, может кто-то помочь мне понять, что не хватает в понимании того, как объявить класс.Ошибка C2027: использование неопределенного типа - как объявить класс

error C2027: use of undefined type 'generic_iterator' 
note: see declaration of 'generic_iterator 

Не работает - ошибка показано выше

#include <iostream> 
class generic_iterator; 
class darray 
{ 
public: 
    typedef generic_iterator iterator; 
    darray(); 
    darray(int size); 
    ~darray(); 
    int& at(int index); 
    int& operator [](int i); 
    int* data(void); 
    bool empty(); 
    void fill(int val); 
    void print(); 
    size_t max_size(); 
    iterator begin() {return iterator(ptrarray); } 
    iterator end() { return iterator(ptrarray + size); } 

private: 
    int *ptrarray; 
    int num_elements; 
    int size; 
}; 

class generic_iterator 
{ 
public: 
    generic_iterator(int *ptr); 
    ~generic_iterator(); 
    generic_iterator& operator++();  // pre-increment 
    generic_iterator operator++(int); // post-increment 
private: 
    int *iptr; 
}; 

Работы: Когда весь класс объявлен первым

class generic_iterator 
{ 
public: 
    generic_iterator(int *ptr); 
    ~generic_iterator(); 
    generic_iterator& operator++();  // pre-increment 
    generic_iterator operator++(int); // post-increment 
private: 
    int *iptr; 
}; 

class darray 
{ 
public: 
    typedef generic_iterator iterator; 
    darray(); 
    darray(int size); 
    ~darray(); 
    int& at(int index); 
    int& operator [](int i); 
    int* data(void); 
    bool empty(); 
    void fill(int val); 
    void print(); 
    size_t max_size(); 
    iterator begin() {return iterator(ptrarray); } 
    iterator end() { return iterator(ptrarray + size); } 

private: 
    int *ptrarray; 
    int num_elements; 
    int size; 
}; 

ответ

2

Когда вы объявляете сводку чего-либо перед ее использованием, это называется вперед декларация.

При выполнении прямого объявления функции компилятор имеет все необходимое для анализа кода, который вызывает эту функцию: имя функции, возвращаемый тип, количество аргументов и тип каждого аргумента ,

Но при создании переднего объявления классу компилятор знает только, что этот конкретный символ (generic_iterator в вашем случае) является классом. Впоследствии единственное, что вы можете сделать с ним до того, как оно было полностью определено, - это объявить указатель на него. (И люди с большим знанием C++, чем я, могут знать одно или два дополнительных тайных использования.) Вы не можете вызывать ни одного из своих членов, потому что компилятор еще не знает его структуры. Ваш код пытается вызвать конструктор вашего класса с прямой ссылкой, но компилятор пока не знает о каком-либо таком конструкторе.

Я не знаю, как легко решить эту проблему. У других может быть несколько лучших решений, но способ, которым я склонен решить эту проблему, - это переместить весь код, который должен получить доступ к элементам объявленного вперед класса из файла .h в файл .cpp. Итак, в вашем случае в файле .h я просто напишу iterator begin();, а затем в файле .cpp напишу generic_iterator darray::begin() {return iterator(ptrarray); }.

Это будет скомпилировано, потому что в этот момент известно полное определение класса generic_iterator.

+0

благодарит за ответ и исправляет мой жаргон - так работает только способ, чтобы обойти ошибку - или есть другой способ объявления объявления в таких случаях? – ifelse

+0

@ifelse Я изменил свой ответ. –

+1

Aha !!! Я получил его сейчас, как правило, я объявляю в .cpp, и на этот раз я объявил его inline и что у меня возникла ошибка. Думаю, теперь я под ним лучше .. спасибо много! – ifelse

3

необходим компилятор знать определение класса generic_iterator, который анализирует эти определения функций

iterator begin() {return iterator(ptrarray); } 
iterator end() { return iterator(ptrarray + size); } 

В противном случае он не может сказать, является ли этот код правильным, является ли класс generic_iterator конструктором, который может быть вызван одним аргументом.

Учтите, что было бы правильным объявить постоянный оператор нижнего индекса вместе с непостоянным оператором. Например

int& operator [](int i); 
const int& operator [](int i) const; 

или

int& operator [](int i); 
int operator [](int i) const; 

Также попробуйте использовать спецификатор const с функциями-членами, которые не изменяют сам объект, как, например empty или max_size или, может быть, print

bool empty() const; 
void print() const; 
size_t max_size()const; 
+0

спасибо за указатели, относящиеся к другим функциям класса - так что рабочий путь, который я показал фрагмент, был бы единственным способом объявить класс, т. Е. Определить его полностью сначала, прежде чем использовать его в другом классе - или какую-то другую форвардную декларацию мне нужно иметь в виду? – ifelse

+0

@ifelse Вы можете определить эти функции вне определения класса (они будут объявлены только в определении класса) после определения класса итератора. –

+0

получил это - спасибо! – ifelse

 Смежные вопросы

  • Нет связанных вопросов^_^