Define classes without header files?

I’m trying to create a class and then pass an instance of said class to a global function and I’m getting compile errors. I’ve written the following example to showcase my issue.

class MyClass {
    public:
        MyClass();
        void test();
};

MyClass::MyClass() {}
void MyClass::test() {}

void setup() {
    MyClass myObj();
    someOtherFunction(myObj);
}

void someOtherFunction(MyClass obj) {
    obj.test();
}

Error:

the_user_app.cpp:4:24: error: variable or field 'someOtherFunction' declared void
the_user_app.cpp:4:24: error: 'MyClass' was not declared in this scope
the_user_app.cpp:4:33: error: 'obj' was not declared in this scope
the_user_app.cpp: In function 'void setup()':
the_user_app.cpp:19:28: error: 'someOtherFunction' was not declared in this scope
make: *** [../the_user_app.o] Error 1

From what I’ve found searching the net, it looks like the compiler rearranges the code a bit - putting global functions up above the inline class declaration, and as such, MyClass would not be declared yet.

The universal answer it seems is to put class definitions in their own header files, but working in the cloud IDE I cannot create and include separate header files. Would someone be so kind as to point me in the right direction?

Thanks,
Chris

1 Like

Hi @crstffr,

You’re absolutely right, the compiler does rearrange the code a bit. I’m guessing if you add your own function declaration “void someOtherFunction(MyClass obj);” after the class, I think the compiler will see that it has been added already and should compile as normal. I haven’t tested this on my end, but I’ll also use this code sample to fix this behavior in the future.

Thanks,
David

Hi @crstffr - this is a limitation of our current implementation that only allows single files. We are working on adding the capability for multiple files and external libraries, but we’re not there yet. In the meantime, if you need C++ libraries, I would encourage you to check out the options for building locally and programming the Core over USB:

Sorry we don’t have a better solution available currently!

If it helps, I just wrote my very first C class last week for a thermistor. I basically looked at the DHT22 class and then used it as a guide to create my Thermistor class. I think the code is pretty readable (even though I didn’t comment it since I didn’t know what I was doing) and may make a decent guide for constructing your own class – https://gist.github.com/wgbartley/8301096

Thanks for the code. I’ve written a few classes for Arduino but never have I tried to pass an instance of a class to another function, which is where I was having issues here.

In the mean time, I just figured a different way about it without needing to pass the object.

1 Like

You just went above my pay grade!

But you have to love programming -- there's always more than one way to skin the proverbial cat!

1 Like

Thanks @Dave and @zach. I figured as much seeing as the position of the global function didn’t seem to make any difference. I like the ability to flash the firmware over the air, so I’ll just be patient, nothing I’m doing is mission critical by any means :).

1 Like

As a workaround, this compiles (sorry, I modified the code to use references, because I’m just being picky):

class MyClass {
public:
    MyClass()
    {
    }
  
    void test()
    {
    }
}; 

void setup()
{
    void someOtherFunction(MyClass &obj);

    MyClass myObj;
    someOtherFunction(myObj);
}

void someOtherFunction(MyClass &obj) 
{
    obj.test();
}

void loop() 
{
}

Hey that's cool, I don't fully know what I'm doing with C, so that kind of stuff helps. Thanks!

Uh, I’m really not trying to play the anal-retentive part, but this is actually C++, not C. :blush:

Ha! Alrighty then. I've always just searched for arduino when researching my hardware programming issues, so I really never even knew if it was C or C++. Thanks for clarifying.

With pointers:

class MyClass;
void someOtherFunction(MyClass * ptr);

class MyClass {
    public:
        MyClass();
        void test();
};

MyClass::MyClass() {}
void MyClass::test() {}

void setup() {
    MyClass * myPtr;
    myPtr = new MyClass();
    someOtherFunction(myPtr);
}

void loop() {
    
}

void someOtherFunction(MyClass * ptr) {
    ptr->test();
}

With pointers:

As much as I like pointers, they tend to be confusing for novice programmers, and they're generally not recommended in C++ unless you understand the issues: When should I use references, and when should I use pointers?, C++ FAQ

For example, users can safely play with the example code above (the one that uses references). On the other hand, if a novice programmer innocently moves the pointer version of the code from setup() to loop() (hey, not everyone's a pointer expert), bad things will happen:

void setup()
{
    // blah ...
}

void loop()
{
    MyClass * myPtr;
    myPtr = new MyClass();
    someOtherFunction(myPtr);
    // eventual kaboom
}

If the reference-using code was used, there wouldn't be any problems.

I would say to anyone coding anything:

Make sure you do your homework first before you even start writing your header.

Beware, dragons lie here. :dragon_face:

Oh yeah, and… it’s fun to wake up the dragons! :fire:

1 Like