I'm used to designing with an MVC-like pattern in which a core class creates an instance of an extension class, handing the extension a pointer to itself, so that the extension can call the core class' methods. When I try to do this in Arduino, it complains that the class name doesn't name a type. The header files containing all class prototypes are included both in the main sketch file, AND all .cpp files, in which the classes live.
I looked through Google for awhile. There was some advice to use include statements, like #include "../../Extension.h", but I think that's particular to earlier Arduino versions as the compiler complains that the file can't be found if I do that. It makes no complaint when I don't try to use relative paths. So, it's reading the header files, but apparently it doesn't believe what it sees?
The error is,
In file included from Core.h:5,
from Core.cpp:2:
Extension.h:9: error: 'Core' does not name a type
Extension.h:10: error: expected `)' before '_theCore'
This is the main sketch, and other files in the same directory:
#include <Arduino.h>
#include "Core.h"
#include "Extension.h"
void setup() {
// This will call Core(), which will instantiate Extension.
// Extension's constructor takes a reference to Core, which
// it then uses to ask it for a variable.
Core theCore = Core();
}
void loop() {
}
Add a forward declaration to the Core class in extension.h
Why?
core.h includes extension.h, so even though extension.h includes core.h, class Extension is declared before class Core, which it uses 'before it is defined', and subsequently does not name a type.
I could be wrong, but give it a try.
#ifndef EXTENSION_H #define EXTENSION_H
#include <Arduino.h> #include "Core.h"
class Core;
class Extension {
public:
Core theCore;
Extension(Core _theCore);
};
What will work is an interface class - a pure virtual class, which acts as an arbitrator between parent and child types.
Some people claim interfaces are the correct way. Bloody long winded way if you ask me.
626Pilot:
I'm used to designing with an MVC-like pattern in which a core class creates an instance of an extension class, handing the extension a pointer to itself, so that the extension can call the core class' methods.
That sort of mutual dependency looks wrong to me. It seems as if you're trying to put the factory inside the product. If you separate out these abstractions you remove the need for any mutual dependency. If you really want both abstractions in the same class then define an interface which your extension class uses to access the core class so that you do not have a mutual dependency between the factory/core and the extension
No, it doesn't by itself. However thankfully there is no need for a base class of virtual functions either.
By changing theExtension & theCore to pointers ( removing the need for the headers until the cpp files ) and using forward declarations like I mentioned ( for both classes ) the problem is solved far easier.
PeterH:
That sort of mutual dependency looks wrong to me.
It works quite well in the field! I've been using it for ages, but in other programming languages. The pattern I use here looks like a star topology, in which the Core is the central hub, and the Extensions are contained within it, and talk to it, and to each other, through it. For example, if I'm rendering a web page, Core will contain things like User and View. Code in a Web template will cause View to query Core.User.userName for the name of the logged-in user. Likewise, if the user changes their username, the View can tell Core.User to make it happen. This is arbitrated through strict access rules and thorough input sanitization.
This may bear some similarities to things in the Design Patterns book, and I'm sure it could violate some principle therein. I don't use it all the time, but where it fits, it works REALLY well.
MattS-UK:
What will work is an interface class - a pure virtual class, which acts as an arbitrator between parent and child types.
Some people claim interfaces are the correct way. Bloody long winded way if you ask me.
Thank you VERY much!!! This works as it should.
I split off the .h files with inline methods into .h/.cpp. I also had to remove the ~Core(); from the ifCore.h prototype because it was causing it not to compile. And now it DOES compile!
626Pilot:
It works quite well in the field! I've been using it for ages, but in other programming languages.
Same here, used it in other languages. It's quite a powerful form of polymorphism and very useful in event driven systems.
My own little speciality is networks, where I might have an over arching server object, spawning multiple connection objects, which all need to tell the server when certain things happen, like a timeout for instance. Essentially, an interface is an appropriate method for many different things (types) refreshing a single state machine. For a single type, I think it is a bit long winded and introduces an additional layer of complexity at design time. With C/C++ you can probably avoid the need for an interface by passing a pointer to a function.
I split off the .h files with inline methods into .h/.cpp. I also had to remove the ~Core(); from the ifCore.h prototype because it was causing it not to compile. And now it DOES compile!
Interesting. I compiled the example as far as creating an instance of Core. I didn't try to run it on a board. Whilst I wrote the example, it was in the back of my mind that if I ever used it for real, I would want to be very certain objects were destroyed as they should be.
Anyhow, nice to see a bit of OOP in the Arduino forum
@pyro. Here is what I get when I compile the example
Compiling 'Core1' for 'Arduino Yún'
Binary sketch size: 6042 bytes (used 21% of a 28672 byte maximum) (4.25 secs)
Minimum Memory Usage: 185 bytes (7% of a 2560 byte maximum)
AVR Memory Usage
----------------
Device: atmega32u4
Program: 6042 bytes (18.4% Full)
(.text + .data + .bootloader)
Data: 185 bytes (7.2% Full)
(.data + .bss + .noinit)
text data bss dec hex
0 6042 0 6042 179a