synodiporos
synodiporos

Reputation: 31

C++ for arduino - error: class does not name a type

I'am expert in java but not in C and in C++. I'am trying to develop a C++ api for my Arduino projects. There are two classes in 4 separate files (headers .h and .cc files). The class CDScreen is a container of CDFrame objects.

What i want to do now is to keep track of the parent container of the CDFrame entries. In other words, the CDFrame object need to know its container (parent). For that purpose i added a property called "parent" of type CDScreen into the CDFrame class.

This addition in header of class CDFrame cause a complile error in header of class CDScreen ('CDFrame' does not name a type CDScreen.h). Specifically, i notice that the problem is caused from the declaration of the CDScreen.h file at the top of the .h file of the CDFrame. The compilation seems that it stops at that point.

What goes wrong here? How is it possible to create a class A with property of B which in turn has properties of A? Is this an issue or my developing way is totally in java-like fashion?

the CDFrame.h file:

#include "CDScreen.h" //<- this cause the problem
#include <stdint.h>

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

and the CDScreen.h file:

#include "CDFrame.h"
#include <stdint.h>

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}

Upvotes: 1

Views: 1347

Answers (2)

drRobertz
drRobertz

Reputation: 3638

The problem is that C++ is declare before use, so any type must be declared before it can be used. (Where "before" means "above in the source text".) For types with circular dependencies, that means that the types need to be declared before they can be defined. That is done with a forward declaration, which simply introduces the name, without defining the type. In this case, such a declaration would be class CDScreen;.

(Note that after a forward declaration, you can use pointers to the type, but not actual objects of the type as it is not yet defined.)

As opposed to Java, C++ does not require you to place each class in a separate file. In fact, it is often preferable to put a group of classes that belong/operate together in a single header file.

In particular in cases like yours with circular dependencies, putting each class in a separate header file/compilation unit can turn quite brittle. For instance, the order in which the user includes the header files can matter, leading to seemingly random compilation errors.

In your case, I would argue that the best option is to put the classes in the same file, and add forward declarations at the top.

#include <stdint.h>
class CDScreen;  // forward declarations
class CDFrame;   // (this one is not strictly necessary but put in for symmetry/consistency)

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}

Upvotes: 2

Tuğberk Kaan Duman
Tuğberk Kaan Duman

Reputation: 950

Years ago when I was working on a C++ project happened to me too. Defining classes solved the problem.

You can see my example files here:

https://github.com/tkduman/project-x/blob/master/monster.h

https://github.com/tkduman/project-x/blob/master/player.h

They have class monster; and class player; in each other, otherwise it won't work.

Try to update your files as:

CDFrame.h file:

class CDScreen; // add this
#include "CDScreen.h"
#include <stdint.h>

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

CDScreen.h file:

class CDFrame; // add this
#include "CDFrame.h"
#include <stdint.h>

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}

Upvotes: 2

Related Questions