Basic question about libraries and classes

Am coming to Arduino from Swift and Python and am struggling with a very basic question on how to arrange classes / libraries.

Am trying to create a BIOTDevice class that contains a pointer to a BIOTThing object.

Here is BIOTDevice.h

#ifndef BIOTDevice_h
#define BIOTDevice_h

#include "Arduino.h"
#include "BIOTThing.h"

class BIOTDevice {
public:
BIOTDevice();
void setThing(BIOTThing *thing);
BIOTThing *_thing;
};

#endif

Here is BIOTDevice.cpp
#include "Arduino.h"
#include "BIOTDevice.h"
#include "BIOTThing.h"

BIOTDevice::BIOTDevice() {
Serial.println("BIOT Device init");
}

void BIOTDevice::setThing(BIOTThing *thing){
Serial.println("Setting thing in device");
_thing = thing;
_thing->sayHello();
}

Here is BIOTThing.h
#ifndef BIOTThing_h
#define BIOTThing_h

#include "Arduino.h"
#include "BIOTDevice.h"

class BIOTThing{
public:
BIOTThing();
void sayHello();

};

#endif

Here is BIOTTHing.cpp
#include "Arduino.h"
#include "BIOTThing.h"
#include "BIOTDevice.h"

BIOTThing::BIOTThing() {
Serial.println("BIOT Thing init");
}

void BIOTThing::sayHello() {
Serial.println("BIOT Thing says hello");

}

Here is the main ino file
#include "BIOTDevice.h"
#include "BIOTThing.h"

void setup() {
Serial.begin(115200);
Serial.println("\nMain Program start");
BIOTDevice device = BIOTDevice();
BIOTThing thing = BIOTThing();
device.setThing(&thing);
}

void loop() {}

Im on a Mac. The .h and .cpp files are all stored in the same folder as the main.ino file

The error message is
In file included from sketch/BIOTThing.h:5:0,
from sketch/BIOTThing.cpp:2:
BIOTDevice.h:10: error: 'BIOTThing' has not been declared
void setThing(BIOTThing *thing);
^
BIOTDevice.h:11: error: 'BIOTThing' does not name a type
BIOTThing *_thing;
^
exit status 1
'BIOTThing' has not been declared

I think this has to do with file locations but having spent an hour, cannot figure out where else to put it (tried libraries sub folder under a BIOT folder as well).

Thank you for any help!

please use code tags - preferably per file

adding "class BIOTThing;" to BIOTDevice library seems to fix the problem.

BIOTThing.h

#ifndef BIOTThing_h
#define BIOTThing_h

#include "Arduino.h"
#include "BIOTDevice.h"

class BIOTThing{
public:
    BIOTThing();
    void sayHello();

};

#endif

BIOTThing.cpp

#include "BIOTThing.h"
#include "BIOTDevice.h"

BIOTThing::BIOTThing() {
    Serial.println("BIOT Thing init");
}

void BIOTThing::sayHello() {
    Serial.println("BIOT Thing says hello");

}

BIOTDevice.h

#ifndef BIOTDevice_h
#define BIOTDevice_h

#include "Arduino.h"
#include "BIOTThing.h"

class BIOTThing; // forward declaration

class BIOTDevice{
  public:
    BIOTDevice();
    void setThing(BIOTThing &thing);
    //BIOTThing *_thing;
};

#endif

BIOTDevice.h

#include "BIOTDevice.h"
#include "BIOTThing.h"


BIOTDevice::BIOTDevice() {
  Serial.println("BIOT Device init");
}

void BIOTDevice::setThing(BIOTThing &thing) {
  Serial.println("Setting thing in device");
  thing.sayHello();
}

main code:

#include "BIOTDevice.h"
#include "BIOTThing.h"

void setup() {
  Serial.begin(115200);
  Serial.println("\nMain Program start");
  BIOTDevice device;
  BIOTThing thing;
  device.setThing(thing);
}

void loop() {}

I am not sure I can say this right , but here it goes.
Compiler works on each .h / .cpp pair individually, first build their .o files, then on main.cpp.
So each pair has to have access to required #include files.
I am not sure how to instruct the Arduino usage to GCC to make sure the files are correctly , in right sequence, included by setting the compiler "includes" option outside .h /.cpp pair.

I would try dummy .h .cpp files without #include(s) , maybe compiler will give you good verbose output so see the actual sequence of their compilation.

sherzaad:
adding "class BIOTThing;" to BIOTDevice library seems to fix the problem

Since you're doing a forward declaration, trying removing '#include "BIOTThing.h"' from BIOTDevice.h.

your function:

void BIOTDevice::setThing(BIOTThing* thing) {

expects a pointer to a BIOTThing.

you need the address of the object here:

device.setThing(thing);

like this:

device.setThing(&thing);

ADDED:

#include "BIOTDevice.h"
#include "BIOTThing.h"

it appears that these classes are somewhat related, so why are they in two sets of header/implementation files?

BulldogLowell:
ADDED:

#include "BIOTDevice.h"

#include "BIOTThing.h"




it appears that these classes are somewhat related, so why are they in two sets of header/implementation files?

Primarily because of the length of each of the .cpp files.

BIOT:
Primarily because of the length of each of the .cpp files.

???

sherzaad:
adding "class BIOTThing;" to BIOTDevice library seems to fix the problem.

You are right! I guess it has to do with the compile sequence. Thank you so much.

BulldogLowell:
so another beginner question here .. :slight_smile:

If there are multiple and long classes under the covers, do they all HAVE to go into the same file? Was trying to organize the files to be of manageable length..

BIOT:
If there are multiple and long classes under the covers, do they all HAVE to go into the same file? Was trying to organize the files to be of manageable length..

I cannot tell if you are trying to learn to write a class or actually write a class, so it is hard to give any advice.

the only think I can say is that programmers spend many hours of thought and effort trying to simplifying their code. If you are developing a library that has several co-dependant classes, why have the programmer (i.e. you) have to include two headers?

Why does BIOTThing.cpp include BIOTDevice.h? If it didn't, the forward declaration in BIOTThing.h wouldn't be required. I can't see that the BIOTThing class needs to know anything about the BIOTDevice class, including whether or not there is even such a thing as a BIOTDevice class.