Why is #endif included at the end of the .h page? - c++

Is it bad practice to put #endif at the beginning of a c++ header file after #ifndef and #define? If so, why?
This question does not touch on why #endif is at the end - which is specifically what i was googling for.
For example
//cDate.h
#ifndef CDATE_H_EXISTS
#define CDATE_H_EXISTS
#include <string>
class cDate {
private:
std::string day;
std::string month;
std::string year;
public:
void setDate(std::string, std::string, std::string);
std::string getDate(int);
}; // end class def
#endif
vs
//cDate.h
#ifndef CDATE_H_EXISTS
#define CDATE_H_EXISTS
#endif
#include <string>
class cDate {
private:
std::string day;
std::string month;
std::string year;
public:
void setDate(std::string, std::string, std::string);
std::string getDate(int);
}; // end class def

First example, it is include guard
Second example, it is nothing-guard.

It doesn't accomplish its task; including this header file again will include all the lines again.
Consider the if statements:
if (condition) {
<do something>
}
vs.
if (condition) {
(void) 0;
}
<do something>
The condition is the #ifndef (if not defined), the opening brace is the initial condition, and the closing brace is the #endif.

You need to exclude the full contents of the file if it's already processed.
The purpose is not to #define the header guard - that's a useful(ish) side effect. The purpose is to ensure the header content is loading only once.

While, subtle, the difference is huge. Assuming you were to place the #endif right after your #define statement at the top, that definition would be completely blank, and if there is a situation where your header file is being included more than once, the file will still be compiled and cause issues because nothing was defined.
Once the flip side, the #endif is supposed to be at the very end to set the definition as the ENTIRE file and its code contents, so that if it is included more than once, none of the file will be executed in excess.

Related

Is it possible to add an include directive inside of a class definition?

I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.

C++ Class redefinition error - I cannot figure this out for the life in me

Any help on why I am getting a 'C2011 'Transaction':'class' type redefinition? I'm sure it's glaringly obvious but I cannot for the life of me figure it out. Please help.
transaction.h
#include <string>
class Transaction
{
private:
int amount;
std::string type;
public:
Transaction(int amt, std::string kind);
std::string Report();
};
transaction.cpp
#include "transaction.h"
using namespace std;
Transaction::Transaction(int amt, std::string kind):amount(amt), type(kind)
{
}
string Transaction::Report()
{
string report;
report += " ";
report += type;
report += " ";
report += to_string(amount);
return report;
}
You can either use a header guard in the header file which will make sure you never ever more than once define a class or struct etc. in any other cpp file.
To add a header guard you can simply do this:
#ifndef TRANSACTION_H
#define TRANSACTION_H
// your header file
#endif
Or simply add
#pragma once
to all your header files and you're good.
You need to use include guards in transaction.h:
#if !defined(your_symbol)
#define your_symbol 1
/*ToDo - code here*/
#endif
Where, your_symbol is typically an embellishment of the name of the file. Be careful not to use a leading double underscore or a single leading underscore followed by a capital letter as they are reserved symbols.
This prevents the class declaration from being included more than once in any compilation unit.
You can use #ifndef your_symbol in place of my first line, and drop the 1 from the second line, or perhaps even just use a #pragma once directive at the top of the file, but the version I present works on every compiler I've ever come across.
In your header try this:
#ifndef TRANSACTION //If transaction has never been defined before
#define TRANSACTION //Define transaction
//Content of your header
#endif
This header guard will probably help you. Indeed it will prevent your header from being included multiple times which leads to redefinitions. If you include your header just once you don't need these guards, but it doesn't hurt to have them anyway.
Alternatively, you can use #pragma once at the beginning of your header.
If you want to read more about them, check wikipedia

struct in separate header file causing problems in C++

I have a struct Tree that is defined inside Class Parser. I have methods defined in Parser that take Tree as input.
void Parser::InputTree(const Tree& input) {
//uses data from Tree
}
Everything seemed to be working fine. But then I needed to use Tree outside the class. So I decided to define struct Tree in a separate header. I included this header in the header file for Parser. While I see no errors in the header file of Parser, the source file shows errors on my Eclipse. Says member declaration not found pointing to method InputTree.
My question is, first off is this the right strategy to define a struct in a separate header? Second, what am I doing wrong? Third, I have some enum types also that I want to use across classes. Where do I define it?
Right structure:
parser.h
#ifndef _PARSER_H_
#define _PARSER_H_
#include "tree.h"
class Parser {
void InputTree(const Tree& input);
};
#endif /*_PARSER_H_*/
parser.cpp
#include "parser.h"
void Parser::InputTree(const Tree& input){
// use data from Tree
}
tree.h
#ifndef _TREE_H_
#define _TREE_H_
struct Tree {
//nodes
};
#endif /*_TREE_H_*/
Including parser.h includes tree.h and hence, struct Tree is available in the main compilation unit.
A simple rule of the thumb I usually follow, is if a custom datatype (i.e. struct, enum, etc.) is used only within a class, I end up defining this datatype within the definition of the class.
But if the same type is required to be used across 2 or more classes (without any parent-child relationship), I end up defining the type either within another header file and usually within a namespace (when the types or related in some fashion).
And yes you could use multiple such namespaces within multiple header files (to group related types), if you feel the need to distinguish them, but I've just show a simpler example using a single namespace:
/* MyNamespace.h */
#ifndef MY_NAMESPACE_H
#define MY_NAMESPACE_H
namespace MyNamespace {
struct Tree {
int a;
char b;
};
enum SomeEnum {
VALUE_0 = 0,
VALUE_1 = 1,
VALUE_2 = 2
};
}
#endif
/* Parser.h */
#ifndef PARSER_H
#define PARSER_H
#include "MyNamespace.h"
class Parser
{
public:
void InputTree(const MyNamespace::Tree& input);
};
#endif
/* Parser.cpp */
#include "Parser.h"
void Parser::InputTree(const MyNamespace::Tree& input)
{
}
Yes, it is a correct strategy to define the struct in a separate header file.
What you are doing wrong is hard to say without more input - but it probably has to do with includes, include-guards or namespace mismatches.
And finally, you should declare the enums in another header file, with proper include guards.

Why there is no replacement of the preprocessor directives?

The format of define preprocessor directives are:
#ifndef SIZE
#define SIZE 10
int hello[SIZE];
#endif
But when I look at the following code, there is no replacement for the preprocessor directives:
#ifndef CREDIT_CARD_H // Avoid repeated expansion
#define CREDIT_CARD_H
#include <string> // Provides string
#include <iostream> // Provides ostream
class CreditCard
{
public:
CreditCard(const std::string& no, // Constructor
const std::string& nm, int lim, double bal = 0);
// Accessor functions
std::string getNumber()const { return number; }
std::string getName() const { return name; }
double getBalance() const { return balance; }
int getLimit() const { return limit; }
bool chargeIt(double price); // Make a charge
void makePayment(double payment); // Make a payment
private: // Private member data
std::string number; // Credit card number
std::string name; // Card owner's name
int limit; // Credit limit
double balance; // Credit card balance
};
std::ostream& operator<<(std::ostream& out, const CreditCard& c);
#endif
What does this mean?
You can say #define FOO, which means that #ifdef FOO will be true, but FOO doesn't have any replacement text. This is useful precisely for conditional checks like the include guards.
It can also be useful for platform-specific extensions, which you want to be empty in the general case:
#ifdef WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
API void foo();
That type of directive pastes in the file depending on the condition:
#ifndef SIZE
//whatever
#endif
Whatever is between the #ifndef and #endif is seen by the compiler only if SIZE wasn't defined.
The same happens for the second piece of code:
#ifndef CREDIT_CARD_H // avoid repeated expansion
#define CREDIT_CARD_H
//....
#endif
The class definition and includes will only be seen if CREDIT_CARD_H was not defined beforehand. This is known as an include guard.
You don't have to define a macro as something, you can just say #ifdef SIZE without actually "setting" size to anything, just defining it.
It's an include guard to ensure that the file only gets included once.
#include "CreditCard.h"
#include "CreditCard.h"
The second time it's included CREDIT_CARD_H is already defines so it skips the whole definition.
Now you wouldn'd directly include a file twice like that, but it's common that one include file includes another and this stops any duplication definitions from happening.
The actual value is never used, only the fact that it's now defined
I think what you are looking for is #pragma once
https://en.wikipedia.org/wiki/Pragma_once

Compile error when I use C++ inheritance

I am new to this website and I am trying a simple inheritance example in C++.
I checked my code lots of times and I really see nothing wrong with it, however the compilers gives me errors:
my code:
#ifndef READWORDS_H
#define READWORDS_H
using namespace std;
#include "ReadWords.h"
/**
* ReadPunctWords inherits ReadWords, so MUST define the function filter.
* It chooses to override the default constructor.
*/
class ReadPunctWords: public ReadWords {
public:
bool filter(string word);
};
#endif
And the messages I get from the compiler:
ReadPunctWords.h:11: error: expected class-name before '{' token
ReadPunctWords.h:13: error: `string' has not been declared
ReadPunctWords.h:13: error: ISO C++ forbids declaration of `word' with no type
Tool completed with exit code 1
I am really not sure where I get it wrong as it looks just fine to me?
Thank you for any mistakes you might spot.
You need to include string:
#include <string>
That said, don't use using namespace! Especially at file-scope, and definitely not in a header file. Now any unit that includes this file is forced to succumb to everything in the std namespace.
Take that out, and qualify your names:
bool filter(std::string word);
It's arguable more readable, too. Additionally, you should take your string as a const&:
bool filter(const std::string& word);
To avoid having to copy the string unnecessarily. Lastly, your header guards seem off. Should they be changed? As of now, they seem like the same ones that would be used in your other header, which might effectively stop it from being included.
If you define READWORDS_H and then include ReadWords.h, and if that also has:
#ifndef READWORDS_H
#define READWORDS_H
Then nothing in that file will be processed. If that's the case, ReadWords as a class won't be defined, and you cannot inherit from it. Your guard should probably be:
READPUNCTWORDS_H
You need to include <string> and specify the namespace:
#include <string>
using namespace std;
Also, your include guard should probably be named READPUNCHTWORDS_H rather than READWORDS_H.
Edit: On second thought, GMan is right about not putting using namespace in a header file - qualify the string with std::string instead.
This particular form of error is often caused by a type not being defined (at least when the code looks syntactically correct), in this case probably the class ReadWords but maybe also std::string.
You need to include to get std::string, as other posters have written, but also your guard
#ifndef READWORDS_H
#define READWORDS_H
almost certainly conflicts with the guard in ReadWords.h. You need to make sure your guards are distinct in different header files otherwise you will get conflicts like this. You should change the guard to something like
#ifndef READPUNCTWORDS_H
#define READPUNCTWORDS_H
// ...
#endif
In fact, it's better to have even more verbose guards to make sure they don't conflict. We use guards of the form
#ifndef MODULE_OR_PATH_FILE_H_INCLUDED
#define MODULE_OR_PATH_FILE_H_INCLUDED
// ...
#endif
This ensures different modules or libraries with similarly named headers don't conflict, the INCLUDED thing at the end is my own particular foible that makes the guard slightly more readable.
It's also bad practice to place a "using" declaration in a header file, because it places (potentially unwanted or conflicting) symbols in the global namespace everywhere you include the header. Personally, I prefer to retain the namespace for clarity or alias it in cpp files if it's a long one, for example
namespace fs = boost::filesystem;
also looks like something wrong with ReadWords class def (message for line 11)- we need to see .h file
aha - the sentinial def you use prevents the readwords.h include being read
you need
#ifndef _READPUNCTWORDS_H
#define _READPUNCTWORDS_H
I also suspect the include guards. If they are named the same way in both header files, the result should be something like the following when ReadWords.h is pasted into ReadPunctWords.h.
#ifndef READWORDS_H // Is READWORDS_H defined? No, proceeding
#define READWORDS_H // Now it is defined
// Contents of ReadWords.h is pasted in here
#ifndef READWORDS_H // Is READWORDS_H defined? Yes, ignoring the contents of ReadWords.h (skipping til #endif)
#define READWORDS_H
class ReadWords { ... }; // This is never seen by the compiler as the preprocessor removed it
#endif
class ReadPunctWords: public ReadWords { // Error: ReadWords isn't declared...
public:
bool filter(string word);
};
#endif