Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error C2027: use of undefined type - how to declare class

I am running into below error - when I just provide the definition of class first and then declare it later. My understanding was as long as we do that as I have done numerous times for function definition, compiler gets it but seems my understanding is flawed can someone help me understand what is missing part in understanding of how to declare class.

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

Does not work - error shown above

#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;
};

Works : When entire class is declared first

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;
};
like image 555
ifelse Avatar asked Nov 27 '15 21:11

ifelse


2 Answers

When you declare a summary of something before using it, this is called a forward declaration.

When making a forward declaration to a function, the compiler has everything it needs in order to parse code which invokes that function: the name of the function, the type returned, the number of arguments, and the type of each argument.

But when making a forward declaration to a class, the compiler only knows that this particular symbol (generic_iterator in your case) is a class. Subsequently, the only thing you can do with it before it has been fully defined is to declare a pointer to it. (And people with more knowledge of C++ than me might know one or two additional arcane uses.) You cannot invoke any of its members, because the compiler does not yet know its structure. Your code is trying to invoke the constructor of your forward-referenced class, but the compiler does not know of any such constructor yet.

I do not know of any easy way to resolve this problem. Others might have some better solutions, but the way I tend to resolve this problem is by moving all of the code that needs to access members of a forwardly declared class from the .h file to the .cpp file. So, in your case, in the .h file I would simply write iterator begin(); and then in the .cpp file I would write generic_iterator darray::begin() {return iterator(ptrarray); }.

This would compile, because at that moment the complete class definition of generic_iterator is known.

like image 198
Mike Nakis Avatar answered Nov 08 '22 12:11

Mike Nakis


The compiler needs to know the definition of the class generic_iterator whan it is parsing these function definitions

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

Otherwise it is unable to say whether this code is correct that is whether class generic_iterator has a constructor that can be called with one argument.

Take into account that it would be correct to declare a constant subscript operator along with the non-constant operator. For example

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

or

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

Also try to use the qualifier const with member functions that do not change the object itself like for example empty or max_size or maybe print

bool empty() const;
void print() const;
size_t max_size()const;
like image 33
Vlad from Moscow Avatar answered Nov 08 '22 13:11

Vlad from Moscow