-1

I'm putting a class definition and a void function outside the main.cpp, but when at declaration of sports it give me "incomplete type isn't allowed", what can I do?

main.cpp:

#include "importer.h"

int main(){
    object sports[200];  //here it give me the error

importer.h:

extern class object;

importer.cpp:

class object {
public:
    string attributes[5];
    string name;
    int objectsLength = 0;
};
  • 2
    Wow, I didn't even know `extern class name` was possible, what compiler are you using? – JVApen Dec 24 '18 at 18:36
  • Possible duplicate of [C++ Extern Class Declaration](https://stackoverflow.com/questions/7923392/c-extern-class-declaration) – JVApen Dec 24 '18 at 18:38
  • you have the importer.h and importer.cpp backwards. The class needs to be declared in importer.h and defined in importer.cpp. And drop the extern. Then just include the header file and instantiate the class objects as needed. For this class you don't even need an importer.cpp file since it has nothing that needs defining. Defaults are fine. – doug Dec 24 '18 at 18:41
  • 1
    @doug "The class needs to be declared in importer.h and defined in importer.cpp." This seems to be exactly what OP is doing? – cpplearner Dec 24 '18 at 18:47
  • @cpplearner The class is completely declared in the cpp file. The h file just states that the class exists. It can be used to create a pointer to the an object of class but that's about it. For other uses you need the complete class declaration. There is no need for a cpp file for this class. What's in the cpp file should be in the h file. It's the full declaration. – doug Dec 24 '18 at 18:55
  • @doug If you call `class object { ... }` "full declaration" then what do you think is the "class definition"? (As far as what I learn, `class object { ... }` is the class definition.) – cpplearner Dec 24 '18 at 19:04
  • @cpplearner • `class Foo;` is a forward declaration, not a full declaration. – Eljay Dec 24 '18 at 19:07
  • @cpplearner The full class definition includes default items such as the default constructor which is necessary to declare an array of the class objects. The full class declaration, for this class, has no need for defining anything else. Had the class declaration included something like `object();` then it would have need for a cpp file to define it like `object::object(){}` – doug Dec 24 '18 at 19:36
  • I'm probably using terms a bit loosely. A forward class declaration is simply a way of providing a name that can be used for limited purposes such as declaring a pointer to it. A class definition that fully defines it's interface but perhaps not it's member function bodies, can be used to instantiate and operate on objects. Both of these are usually done in header files. Member functions that are declared, but not defined in the class definition are normally in a separate cpp file to prevent multiple instantiations. – doug Dec 24 '18 at 19:49
  • `extern class object;` is not legal in C++. You need to define the class in the header. – n. m. could be an AI Dec 25 '18 at 05:31
  • @doug the standard doesn't have this notion of "full definition". There are declarations, some of those are also definitions, and that's it. There is no further refinement into full definitions vs any other definitions. – n. m. could be an AI Dec 25 '18 at 05:34
  • @n.m. The standard refers to complete types and incomplete types. Complete types require that items such as member functions that are declared but not defined in a header are defined in some other translation unit with certain exxpcetions allowing them to be defined later in the same translation unit. One can certainly say that complete types are fully defined types. – doug Dec 25 '18 at 20:08
  • @doug "Complete types require that items such as member functions that are declared but not defined in a header are defined in some other translation unit". There is no such requirement, You are probably thinking about ODR. It has nothing to do with complete types. Things that are *used* must be defined. A member function that is declared but not used need not be defined. Anyway if you have failed to define a member function that is needed, you don't have a "not fully complete type", you have an ill formed program. – n. m. could be an AI Dec 25 '18 at 21:56
  • @n.m. Yes, it's under ODR, 6.2 note 5 says "Exactly one definition of a class is required in a translation unit if the class is used in a way that requires the class type to be complete." I agree that if a member function is not used anywhere, it need not be defined even if declared. The standard seems to refer to "complete type" as able to contain declared, but not defined, member functions, if not used in the program. This is reasonable, since a declared, but unused member function is superfluous. Can't say I've ever written one. At least intentionally. :) – doug Dec 25 '18 at 22:51
  • @doug A definition of a class does not need to include definitions of any member funtions. Those have separated definitions (when out of line). A definition is not some nebulous distributed thing, it's a kind of a declaration. A class definition begins with a class keyword and ends with a closing brace. A class type is complete at some point iff its definition is visible at that point. Declaring but not defining member functions used to be a common technique before deleted functions were invented. – n. m. could be an AI Dec 26 '18 at 04:47
  • "Declaring but not defining member functions used to be a common technique before deleted functions were invented." Good point, I've done that back in the day with default functions I wanted to disable to prevent usage not applicable to the type. I suppose they could be written to prevent undesired conversions too though I haven't done that outside of template programming. – doug Dec 26 '18 at 06:00

2 Answers2

2
 extern class object;

This is not legal in C++ to begin with. If you are not getting any messages about this line, then your compiler is being unreasonably lax. Try cranking up the warning level.

class object;

is normal and legal. This declaration is enough to define pointers to object, but it is not enough to declare an array (or a single variable) of type object.

object* ptr;      // good
object  var;      // bad
object  arr[100]; // bad

In order to be able to use the last two lines, you need to have the definition of class object visible. This is because the compiler needs to know how big each object is, and how to construct and destroy one.

Technically, a type must be complete before objects of that type could be defined.

You normally make the class definition visible by placing it in the header file.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

I am not sure of the end goal so I do not see a reason to use extern or forward declare in this situation.

Most commonly for declaration is used when to class have to call into each other (ie callbacks) because they cannot include each other's header files. In this case one class is forward declared in the other header and a pointer to the class is declared as a member variable but the source files include the required headers. Note that the size of a pointer is known even if the class itself is not.

A reason to use extern in this case is if importer was compiled as separate static lib. extern it would keep from optimizing out the unused class so that the class could be linked to from another binary.

Consider that when main is called sports[200] is placed on the stack and at this point the size of sports must be known. It is not because this information is in the importer.cpp which is not known to the main.cpp.

The easiest solution is to put the definition in the importer header file but I am guessing there is a reason this was not done originally.

I recommend avoiding forward declaration (when possible) as this turns compile errors into linker errors which are typically more difficult to debug. Extern should be used even less in most situations.