compile error: 'class name' does not name a type

I am getting a compile error when I break up a sketch into header files.
This simple example of composition works when it's all in one file:

class Sub1
{
	public:
		void puts() { Serial.print("Sub1 "); };
};

class Composite
{
	private:
		Sub1 sub1;		// sub object
	public:
		void puts() { Serial.print("Composite "); sub1.puts(); };
};

Composite comp;				// composite object

void setup()
{
	Serial.println("setup");
}

void loop()
{
	comp.puts();

	while(true) { } 
}

But when I break it up into header files, the compiler gives "error: 'comp' was not declared in this scope":
main.ino

#include <comp.h>

extern Composite comp;

void setup()
{
	Serial.println("setup");
}

void loop()
{
	comp.puts(); // error: 'comp' was not declared in this scope

	while(true) { } 
}

comp.h

#include <Arduino.h>
#include "sub1.h"

class Composite
{
	private:
		Sub1 sub1;		// sub1 object
	public:
		void puts() { Serial.print("Composite "); sub1.puts(); };
};

sub1.h

#include <Arduino.h>

class Sub1
{
	public:
		void puts() { Serial.print("Sub1 "); };
};

Please tell me how to fix the compile error.
Thank you.

Try:

#include "comp.h"

I wouldn't expect it to cause that error message so perhaps there are two problems, but I don't see any definition of the variable comp (it is declared as an extern in main.ino but not defined anywhere that I can see) so I suggest you get rid of the extern as a start.

You are also trying to hide the use of Sub1 from the sketch. That will NOT work.

Also, there is a convention that the header and source file names match the class name, INCLUDING case. Fix your names, now.

You are also trying to hide the use of Sub1 from the sketch. That will NOT work.

NOT ?

Why ? I'd assume this is the intention.
Sketch deals with class Composite, nothing else, and it should not matter how that class is implemented internally.

But there seems a similar issue with <Wire.h> , if you use e.g. an ( I2C based ) RTC library.

Why ?

The IDE scans the sketch to see what files to copy to the build directory. sub1.h is not included in the sketch, so it doesn't get copied. Then, when comp.h tries to include it, it isn't there. So, Sub1 will be an undefined class, and comp.cpp will fail to compile.

The IDE does not scan include files it copies for other include files. This may have been an oversight, but ti works out well. Someone can't deliver a library that depends on another mystery library that depends on another mystery library. All dependencies must be identified up front, in the example sketches.

Sketch deals with class Composite, nothing else, and it should not matter how that class is implemented internally.

You're probably right. It probably should not matter, but as far as the Arduino IDE is concerned, it appears that it does. I don't know if it is actually a violation of any C standard somewhere, but I know it doesn't work exactly the same as the other C++ IDE's that I use for other things.

michinyon:
I know it doesn't work exactly the same as the other C++ IDE's that I use for other things.

The Arduino IDE basically ignores conventional 'C'/C++ behaviour, and if you assume that Arduino works just like C++ or vice versa you will be led astray. I would say that the differences (wrt implicitly declared types, #include behaviour and semantics, (buggy) autogeneration of function prototypes) are sufficient to justify Arduino being described as a different language which just happens to share the same syntax as C++. It is at the very least an unusual variant of C++.

Thank you for all your suggestions. But the error persists.
Maybe my Arduino setup is missing something?

I created a simpler 2-file example that reproduces the error.


main.ino

#include <test.h>

void setup()
{
	Serial.println("setup");
}

void loop()
{
	test(); // error: 'test' was not declared in this scope

	while(true) { } 
}

C:\Users\wolf\Documents\Arduino\libraries\demoLib\test.h

#include <Arduino.h>

void test() { Serial.print("test "); }

I copied the test.h file into the folder with main.ino, and changed the include statement to quotes #include "test.h".
The sketch compiles and runs fine like this.

What could be causing the compiler to not find C:\Users\wolf\Documents\Arduino\libraries\test\demoLib\test.h ?

I carefully read about User-created Arduino Libraries on http://www.arduino.cc/en/Hacking/Libraries
I am running Arduino 1.0.5 on Windows 7.

What could be causing the compiler to not find C:\Users\wolf\Documents\Arduino\libraries\test\demoLib\test.h ?

How is it supposed to know that test.h is in a subfolder? If you really feel that test.h belongs in a subfolder, you have to tell the IDE that:

#include "./demoLib/test.h"

The ./ may not be necessary, but I don't put header files in subfolders, so I'm not certain. I don't recommend you doing it either.

Thanks PaulS. I moved the header file into the libraries folder as you suggested C:\Users\wolf\Documents\Arduino\libraries\test.h
But the compiler still gets the same error: 'test' was not declared in this scope.

So, now try putting test.h in test in libraries (where it belongs).

Is this code you're trying to put in a different file supposed to be part of your sketch, or part of an Arduino library? It can't be both, and how to do it correctly depends which thing you are trying to do.

OK, I see what you mean. The header file is now in C:\Users\wolf\Documents\Arduino\libraries\test\test.h
Though still getting the same error: 'test' was not declared in this scope.

I created a test folder in my libraries folder. I created a test.h file in that folder.

I pasted your test.h stuff in that file.

I pasted your sketch in the IDE. When I hit verify, I get this "error" message.

Binary sketch size: 1,596 bytes (of a 30,720 byte maximum)

I uploaded the code, and opened the Serial Monitor. Nothing appears.

I added Serial.begin(9600); to the sketch, selected upload, and I get:

Binary sketch size: 1,958 bytes (of a 30,720 byte maximum)

Opening the Serial Monitor, I see:

setup
test

I'd suggest that maybe you need to scroll back up and see if there are other messages you are not seeing.

PaulS, Thanks for going through all the trouble. But there is nothing to scroll.


I found some notable behavior with the header files on my system.
The following 4 screen shots are of headerTest.ino and headTest.h, which are in the same folder.
The first two screen shots compiled fine.

headerTest.ino


headTest.h

The next two screen shots are the same sketch with two lines moved to the header file.
The num definition in the header file worked, but the #include <Wire.h> did not.
This might be a clue; what does it mean?

headerTest.ino


headTest.h

Header files worked last week. The only thing I can think of that changed since then is that I installed NetBeans IDE and the g++ compiler. Could that have messed the Arduino install?

Sorry this is so difficult to trouble shoot. I appreciate all your suggestions.

PeterH:
Is this code you're trying to put in a different file supposed to be part of your sketch, or part of an Arduino library? It can't be both, and how to do it correctly depends which thing you are trying to do.

Right now the files are part of the sketch. Later the files will be shared with other sketches. If it works well, it will be published for others to use.

wolfv:
PaulS, Thanks for going through all the trouble. But there is nothing to scroll.

I get that error too, but if you change it to:

#include "test.h"

It compiles.