a.h is included in b.h and I include b.h in my source file, do I need to include a.h in my source file as well? - header-files

I am going through an example in a c++ book. And did not understand a certain case.
The main.cpp includes stdexcept.h to use runtime exception. And also includes ErrorHandlingModule.h.
ErrorHandlingModule.h already includes stdexcept.h because of the runtime error parameter it has in the function prototype in it.
The book says I have to include stdexcept.h also in main.cpp. In the source code of the book it is also written that way.
When I remove sdtexcept.h from main.cpp compile passes just fine and program works ok still.
But why the book says that?
Thanks for any answers.
MAIN.CPP:
#include <iostream>
#include <stdexcept>
#include "ErrorHandlingModule.h"
#include "Prompt.h"
// ....
int main(int argc, char* argv[])
{
SAMSErrorHandlingModule::initialize();
do
{
try
{
char Operator = getOperator();
float Operand = getOperand();
cout << Accumulate( Operator, Operand ) << endl;
}
catch( runtime_error RuntimeError )
{
SAMSErrorHandlingModule::handleRuntimeError(RuntimeError);
}
catch(...)
{
SAMSErrorHandlingModule::handleNotaNumberError();
};
}while (SAMSPrompt::UserWantsToContinueYorN("More?"));
return 0;
}
ERRORHANDLINGMODULE.H
#include <stdexcept>
#ifndef _ERROR_HANDLING_MODULE_H
#define _ERROR_HANDLING_MODULE_H
namespace SAMSErrorHandlingModule
{
using namespace std;
void initialize( void );
int handleNotaNumberError( void );
int handleRuntimeError( runtime_error theRuntimeError );
}
#endif // _ERROR_HANDLING_MODULE_H

I think the reason is maintainance. At least, I would do that for this reason. If you eventually decide to switch to "ErrorHandlingModule.h" to something else (e.g. you implement a better error handling strategy and want to use the new one) you don't want the other code into main to break because of this.
This means that if you are using something from stdexcept in your main, apart from using it for input to/output from ErrorHandlingModule, you should include it. Otherwise, I would not include it, since it is not needed when ErrorHandlingModule is not used.
As you noted, this has nothing to do with compilation, as your program compiles just fine if you don't include it into the main. With this respect, however, notice that even if it compiles, it is not always "semantically" correct. In fact, your code might compile even if you remove the inclusion from "ErrorHandlingModule.h" (since stdexcept is included before including ErrorHandlingModule.h). This is the reason why I always prefer to have "..." includes before <...> ones.
Also check this question for a similar discussion.

No, you do not need the #include for stdexcept in both files. The pre-processor will copy the header file into the c file before running through the C compiler. Multiple includes of the same header file can be very problematic which is why the example code uses #ifndef for the header file you are creating to make sure that the header code is only included once. Like Stefano said though, if you no longer include stdexcept and then stop using the ERRORHANDLINGMODULE header file your code will no longer compile.

Related

Does C++ include all headers a included header file includes?

In this example code, I have 3 files:
testHeader.h:
void hello() { }
file1.h:
#include "testHeader.h"
#include <iostream>
void sayHi() { std::cout << "hi" << std::endl; }
file2.h:
#include "file1.h"
void sayHello() { std::cout << "hello" << std::endl; }
If file1.h includes testHeader.h and file2.h includes file1.h, do testHeader.h and its functions become accessible in file2.h? What about <iostream> and its functions?
Unless protected by preprocessor guards in weird ways, yes, you get them all. #include is largely a preprocessor trick, roughly equivalent to dumping the text of the include into the source code, and it's transitive; if you #include <a.h>, you get the expanded form of a.h, including the preprocessor expanded form of all its includes, all their includes, etc., etc. ad infinitum, in a single pass.
Note that it's still a good idea to explicitly include all the things you rely on directly; sure, the other .h files might #include <vector> today, but that's no guarantee the next release will have them if they're not a necessary part of the API being exposed.
It's also worth noting that preprocessor include guards (and/or #pragma once) is used almost universally to mean a .h file's contents don't get included twice (by convention, not a guarantee; in the case of poorly written .h files, or weird ones designed for multiple inclusion with different preprocessor setups it won't be obeyed); there is little to no cost to re-including a header in the .cpp that it already got from a .h you included. On older compilers, without #pragma once and with no special handling for include guards, it might have to load the header a second time, see the guard, and dump nothing on the second include; many newer compilers are smart enough to avoid even that cost. Point is, don't try to optimize by avoiding redundant #includes; every file should have the complete set of #includes needed for the things used in that file, no more, no less.
If you work on older compilers, without #pragma once, then try to do as following.
--- file1.h ---
#ifndef FILE1_H
#define FILE1_H
#include "testHeader.h"
#include <iostream>
void sayHi();
#endif
--- file1.cpp ---
#include "file.h"
void sayHi() { std::cout << "hi" << std::endl; }
--- file2.h ---
#ifndef FILE2_H
#define FILE2_H
#include "file1.h"
#include <iostream>
void sayHello();
#endif
You shouldn't make a body of function in HEADER file. It might cause a compile error for multiple links for the same function. Please write function' prototype and body into Header and Source file seperately.

correct way to include .cpp and .h files in an Arduino sketch

First, the problem:
main sketch file:
char foo; // required to clean up some other problems
#include <Arduino.h> // tried it in desperation, no help
#include "a.h"
void setup(){
Serial.begin(9600);
Serial.println("\nTest begins");
for (int num = -1; num < 1; num++){
Serial.print(num);
if (isNegative(num)){
Serial.println(" is negative");
} else {
Serial.println(" is NOT negative");
}
}
}
void loop(){}
// a.h
#ifndef H_A
#define H_A
boolean isNegative(int x); // Err#1
int anotherOdity();
#endif // H_A
// a.cpp
#include "a.h"
int isNegative(int x){
Serial.println("I can't print this from inside my INCLUDE FILE"); //Err#2
if (x<0) return true;
return false;
}
int anotherOdity(){
char ch[5];
memcpy(ch,"1",1); //doesn't work, memcpy not declared // Err#3
}
The above, as is, doesn't compile and these are the errors I get:
In file included from a.cpp:1:
a.h:4: error: 'boolean' does not name a type
a.cpp: In function 'int isNegative(int)':
a.cpp:4: error: 'Serial' was not declared in this scope
a.cpp: In function 'int anotherOdity()':
a.cpp:11: error: 'memcpy' was not declared in this scope
The first problem is the boolean type, seems to suffer from some name mangling that the Arduino environment does, but that is generally fixed by the char foo; in the main file. And in certain situations, it is. But to use that type in the .cpp file generates this error.
I can see that Errors 2 and 3 are related, but how do I get these in scope? I realise that part of the problem is probably the #include itself (maybe) because Serial and memcpy aren't yet defined/declared? I tried including the the Arduino.h library, but that didn't help. Actually, it did help the boolean problem but only in the case of putting everything in the .h file (as I discuss further below), it doesn't help the above example.
If I put the three files together and have everything in the main sketch (.ino) file, it works as it should. But the idea here is that I want to break out some code and make my sketch more readable.
The closest I got to a solution was found here: http://liudr.wordpress.com/2011/02/16/using-tabs-in-arduino-ide/ where, after running my own tests, I determined that if I put EVERYTHING in a .h file, it works!
For example, leaving the main sketch file unchanged, if I delete a.cpp and create just a.h (as follows) it works!
#ifndef H_A
#define H_A
boolean isNegative(int x){
Serial.println("I can't print this from inside my INCLUDE FILE");
if (x<0) return true;
return false;
}
int anotherOdity(){
char ch[5];
memcpy(ch,"1",1); //doesn't work, memcpy not declared
}
#endif // H_A
This fixes the boolean problem (well.... I still need Arduino.h or char foo;), and it fixes the scope issues.
But it just feels wrong.
This isn't about creating a library of standard functions I could use across various sketches, it's all about breaking my code into smaller (readable) chunks, and keeping them all together in the project folder. I want to do this in the most correct way possible, it just seems to be I'm limited by the IDE. I'm sure I have a suitable understanding of how to put a header and associated .cpp file together (I hope that I have't got that part wrong).
I am totally self taught with everything C/C++ and have only really got into programming micros very recently.
I have researched this through the depths of google and am just continually coming up short.
Without resorting to hacks and keeping it simple for folk like me, how can I best put together the above examples so that the Arduino IDE/gcc will compile it?
edit: I thought I would include just SOME of the tabs I have open here to show that I really have done some research on this!
http://arduino.cc/en/Reference/Include
http://arduino.cc/en/Hacking/LibraryTutorial
http://forum.arduino.cc/index.php/topic,124904.msg938861.html#msg938861
http://forum.arduino.cc/index.php?topic=84412.0 (this is where I found the char foo; solution)
http://liudr.wordpress.com/2011/02/16/using-tabs-in-arduino-ide/
Including .cpp files
Keeping all libraries in the Arduino sketch directory
C++ Header and CPP includes
The reason it doesn't work is that you need to include something in your a.h or a.cpp files.
Try this in your a.h file and then everything should work.
#ifndef H_A
#define H_A
#include <Arduino.h> //needed for Serial.println
#include <string.h> //needed for memcpy
...
The reason for this is that you can think of the compiler separately compiling each cpp file. A #include is in fact just an automated copy paste. When the compiler is coming to compile a.cpp, it doesn't know that Serial.println() exists, because it wasn't defined in a.h, which is the only other text that appears in a.cpp. The reason it works when you put it all in the header is that in your main cpp file you have included Arduino.h before the a.h include, so once those #includes have been copy pasted in its as if you just wrote the code there in the first place.
You can just write all your code in headers, but it isn't advisable for various reasons including efficiency at compile time (but as an arduino program can only be 32k, I don't think compile times are going to get too long!)

Objects in other namespace not found without include, files otherwise identical

I have two functionally identical header files, one of which produces errors for no discernible reason. I must have done something wrong in creating the new (broken) file, but I can't figure out what.
My IDE is Xcode. The project is compiled for Objective C++ using Apple LLVM Compiler 4.1, but the section of code in question is all pure C++, no Objective C.
Here's some code:
NamespaceA.Common.h
#include "../NamespaceB/Common.h"
#include "WorkingClass.h"
#include "BrokenClass.h"
...
../NamespaceB/Common.h
#ifndef NamespaceBCommon
#define NamespaceBCommon
namespace NamespaceB
{
...
}
...
#include "Superclass.h"
...
WorkingClass.h
#ifndef NamespaceA_WorkingClass
#define NamespaceA_WorkingClass
namespace NamespaceA
{
class WorkingClass : public NamespaceB::Superclass
{
public:
WorkingClass();
~WorkingClass();
};
}
#endif
BrokenClass.h
#ifndef NamespaceA_BrokenClass
#define NamespaceA_BrokenClass
// If I don't have this line I get errors. Why?? !!!!!
// This file is exactly identical to WorkingClass.h
// as far as I can tell!
//#include NamespaceA.Common.h
namespace NamespaceA
{
// Parse Issue: Expected class name !!!!!
// Semantic Issue: Use of undeclared identifier 'NamespaceB'
class BrokenClass : public NamespaceB::Superclass
{
public:
BrokenClass();
~BrokenClass();
};
}
#endif
Thank you.
You need to include all of the files that include namespaces and classes that you reference in your code. So, because you reference NamespaceB::Superclass in your BrokenClass.h, you need to be sure to include the file that declares that. In this case, including NamespaceA.Common.h (hopefully) solves this problem, because it includes the file where NamespaceB is included.
As for why you don't have to include NamespaceA.Common.h in your WorkingClass.h, I suspect it's because you just happen to have ../NamespaceB/Common.h included somewhere else.
I found the problem. WorkingClass.cpp was including NamespaceA.Common.h and not including its own header file, rather than including the common file in the header and then including its own header file in the cpp.
I managed to miss the #include in WorkingClass.cpp because I just assumed it was only including WorkingClass.h and not NamespaceA.Common.h.
So in short:
WorkingClass.h
// Class goes here
// No includes
WorkingClass.cpp
// Notice it does not include WorkingClass.h for whatever reason
#include "NamespaceA.Common.h"
NamespaceA.Common.h
#include "../NamespaceB/Common.h"
#include "WorkingClass.h"
#include "BrokenClass.h"
#include "EveryOtherClass.h" ...
BrokenClass.h
// Class goes here
// No includes
BrokenClass.cpp
#include "BrokenClass.h"
// Oh no! Where's NamespaceA.Common.h?
I'm not a big fan of this include scheme, but I'll live with it since it's a large project that I don't want to make sweeping changes to.

C: Using functions from files within in the same project

My question does not link to a direct example, but is more of a question as a whole. When I was coding with C++, I found (after looking through some threads) that in order to use functions from different files that are in the same project, I would either need a header file. So, for example, if I have the main function in a file called "main.cpp" and I wanted to use a function, "prob1()" in another file called "problem1.cpp", I would need to use a header file.
What is confusing me is why I do not have to worry about this for programming in C? When I was programming in C, in order to use functions from different files, I could call the function directly.
Any help/explanation is appreciated. Thanks!
Your C compiler can implicitly declare the function, but you should be doing so yourself. If you turn up the warnings, you'll see something like:
file1.c: warning: implicit declaration of function ‘func_from_f2’
When file1.c is being compiled, this implicit declaration will be used to create an object file and then when linking you have to just hope that the function actually does exist and the declaration is correct so that the object files can be linked together successfully.
If not, the linker will give you an error somewhere along the lines of:
undefined reference to `func_from_f2'
You also don't necessarily need a header file, you can simply include the declaration/prototype of the function in your source file (the #include directive essentially does this for you). ie. the below will work fine without warnings:
file1.c
void func_from_f2(void);
int main(void)
{
func_from_f2();
return 0;
}
file2.c
#include <stdio.h>
void func_from_f2(void)
{
puts("hello");
}
However, it's usually best practice that you do use a header file:
file1.c
#include "file2.h"
int main(void)
{
func_from_f2();
return 0;
}
file2.h
#ifndef FILE2_H
#define FILE2_H
void func_from_f2(void);
#endif
file2.c
#include <stdio.h>
#include "file2.h"
void func_from_f2(void)
{
puts("hello");
}
In C, the compiler will guess the correct prototype if you haven't provided one. It very often guesses wrong, and then your program breaks.
Whether C or C++, it's always a good idea to put forward declarations in a header file that also gets #included into the implementation file, where the compiler can check for mismatch.

C++ Project Layout seems incorrect, compiler can't find implementation files

I'm writing a C++ Package for later use using Code::Blocks.
The project structure looks like this:
cNormal\
cNormal.cdp
src\
main.cpp # for testing purpose
cnormal_defs.h # important compiler definitions
cnormal_storage.h # includes all .h files from "./storage"
storage\
cnarray.h
cnarray.cpp
cnstack.h
cnstack.cpp
bin\
obj\
The cnormal_storage.h:
// cnormal_storage.h
// *****************************************************************
// Includes all necessary headers for the cNormal storage subpackge.
//
#ifndef _cNORMAL_STORAGE_H_
#define _cNORMAL_STORAGE_H_
#include "storage/cnarray.h"
#include "storage/cnstack.h"
#endif // _cNORMAL_STORAGE_H_
To test the classes, i create a main-function in main.cpp.
// main.cpp
// *****************************************************************
// The main-file.
//
#include <iostream>
#include "cnormal_storage.h"
using namespace std;
int main() {
cnArry<int> arr(10);
arr[9] = 999;
arr[0] = 0;
cout << arr[9] << endl;
cout << arr.getLength();
}
But the compiler (gcc) gives me undefined reference to ... errors about cnArray.
Now, the cnarray.cpp includes cnarray.h (as it is the implementation file), so using
#include "storage/cnarray.cpp" works just fine.
It seems like the compiler can't find the implementation of cnarray.h which is located in cnarray.cpp.
I assume it's because of the folder-structure, can you tell me how I can fix this ?
Even adding src\storage to the include directives does not fix it. (And I also don't want to add it to the include-paths as this would be very unhandy for a package.)
Can you post the compilation command that you use?
Seems like you are compiling only main.cpp and not compiling (and thus linking) the other .cpp files.
I could spot the error now, cnArray.h declared a template class and template classes cannot be implmented in another file than they are declared, because the compiler must know about the implementation when compiling, not when linking.
I have found a workaround on the internet to #include the implementation in the headerfile, but exclude the implementation file from compiling.
This works just fine now.
Cheers