borg
borg

Reputation: 243

expected class-name before "{" token

So far I've looked up most of the typical solutions for cases of this error and yet non of them seems to work with my code. I'm using dev-c++

The structure of problematic class is following. m.hh

#ifndef M_H
#define M_H

#include "z.hh"
#include <iostream>
#include <string>


using namespace std;

class M: public Z
{                        /* this line is marked by the compiler as errorneous */
void m1();
void m2();
};

#endif

m.cpp

#include <iostream>
#include <string>
#include "m.hh"

using namespace std;

void M::m1()                    {/*bla bla*/};
void M::m2()                        {/*bla bla*/};
}

EDIT: z.hh

#ifndef Z_H
#define Z_H

#include "m.hh"
#include <iostream>
#include <string>


using namespace std;

class Z;

static Z* s(string g, string i);

#endif

z.cpp

#include "z.hh"
#include <iostream>
#include <string>


class Z
{


public:
    string i;
    string g;

    void set_i(string im)                       {i = im;}
    string get_i()                              {return i;}
    string get_g()                          {return g;}
    virtual void m1()=0;
    virtual void m2()=0;
    Z* s(string g, string i)    {
        Z * z;
        if(g=="m"){
            M * z = new M;

        }
    }

};

Thanks!

Upvotes: 1

Views: 480

Answers (3)

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16017

Well, the z.cpp file is actually a class declaration and should be a header file. A forward decalaration is only sufficient when you deal with pointers to that class, but not for inheriting from one (the compiler does need to know z's class layout for that).

The z.hh is not really needed, and the function declaration in it is not what you think (it's not a member function declaration). You can delete it and rename z.cpp to z.hh.

Ok, the exchange with @Luchian Grigore made me realize what you probably wanted and why you had "two z.hh". Z is to produce an M, but M inherits from Z, so there is a circular dependency. In C/C++ the way to break such a circle is to limit what one of the classes needs to know from the other: In order to declare a member function s that produces a pointer to a new M Z's class declaration only needs a typename M, not a the whole class declaration. So just a forward declaration (class M;) that introduces the type name M into the declaration of Z is enough; if the pointer to the M object is returned as a pointer to the base, Z, M's name is not even needed at all when Z is declared.

The definition of the factory function (be it file static or a member function) needs, if it is to produce an M, M's complete declaration though. That would be in a seaparate cpp file, which would include a complete header with M's full declaration.

Upvotes: 1

Luchian Grigore
Luchian Grigore

Reputation: 258568

Remove #include "m.hh" from z.hh to fix the circular include.

Upvotes: 3

Filip Ros&#233;en
Filip Ros&#233;en

Reputation: 63797

THE PROBLEM

You cannot derive from an incomplete type, which is what Z is in m.hh.

Upon deriving from a type the compiler must know the definition of said type. Just imagine you are trying to call a derived member function from Z on an object of type M, how would the compiler know if such call is a valid construct without knowing if Z actually declares such member?

And, a more relevant point, how would M be able to initialize Z without knowing what Z is?


THE SOLUTION

Move the definition of class Z to z.hh, and leave the definitions of its member functions in z.cpp (the same way you have split up M across m.hh, and m.cpp).

Upvotes: 2

Related Questions