What your code looks like to the compiler (note I have not processed the include statements as that, while more accurate, would make quite a mess):
#pragma once
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
using namespace std;
class
{
public:
;
(string newName, newLevel, newReason);
void setName(string newName);
void setLevel(string newLevel);
void setReason(string newReason);
string getName();
string getLevel();
string getReason();
void print();
private:
std::string name;
std::string level;
std::string reason;
};
void do_something()
{
cout << "Doing something";
}
Why is this?
#define EndageredSpecies
tells the preprocessor to replace EndageredSpecies
wherever it finds it with whatever is on the line after #define EndageredSpecies
, absolutely nothing in this case, so
class EndageredSpecies
is now
class
etc...
You have to be VERY careful with a #define
macro. They are amazingly simple in execution. They have no brains whatsoever. If they see the token they've been told to replace, they replace it. Period. I once made the mistake of defining int strlen;
to contain the length of a string.
Big Mistake.
It turned out the strlen
function was implemented as a macro. int strlen;
became int <whole function body here>;
. I think I burned most of an afternoon figuring that out.
Do not fear the macro, but you have to use it very carefully.
What you really want is more like
#pragma once
#ifndef UNIQUE_AND_NEVER_REPEATED_IDENTIFIER
#define UNIQUE_AND_NEVER_REPEATED_IDENTIFIER
// note how this is above the includes. Don't want to re-include them
#include <iostream>
#include <string>
#include <conio.h>
// do not use using namespace std; in a header. It's a very nasty surprise
// to other programmers.
class EndageredSpecies
{
public:
EndageredSpecies(); // added brackets
EndageredSpecies(std::string newName, // added std namespace
std::string newLevel,
std::string newReason);
void setName(std::string newName);
void setLevel(std::string newLevel);
void setReason(std::string newReason);
std::string getName();
std::string getLevel();
std::string getReason();
void print();
private:
std::string name;
std::string level;
std::string reason;
};
void do_something()
{
std::cout << "Doing something";
}
#endif
An Aside:
#pragma once
and
#ifndef EndageredSpecies
#define EndageredSpecies
#endif
are two ways to make an include guard. You can use both, but typically you don't need to.
#pragma once
is not part of Standard C++, so you can't count on it being supported. Any pragma
that a compiler does not support it is allowed to silently discard, leading to confusion, disaster, and possibly no useful error messages. That said, most compilers these days implement once
. once
likely has not been Standardized because it has severe failure cases in complicated build environments. Don't do anything sneaky and it works just fine.
#ifndef EndageredSpecies
#define EndageredSpecies
#endif
Works all the time everywhere. It's problems are the likes of what the asker has experienced.
Do not repeat a include guard identifier. Ever. For any reason.
Name include guards so that they will be next to impossible to repeat unless you are crazy. Sadly Norman Bates nailed it: We all go a little mad sometimes. To protect against temporary madness, make it as obvious as possible so when you are not mad later, you can see that the used identifier does not make sense where it is being used and change it.
You typically only want one or the other type of include guard, but there can be advantages to using both. If #pragma once
is not supported or fails, you don't get the nasty surprise. If it is supported, there are often performance benefits from not having to look at the included file at all.