"identifier is undefined" when calling function from a header file - c++

All I'm trying to do is create a separate class to hold my Hello World function (this is for a class), but I am getting an "identifier is undefined" compiler error. What is the issue?
Here is my main function (helloworld.cpp):
#include <iostream>
using namespace std;
int main() {
print_me();
system("pause");
return 0;
}
And here is the header class (helloworld.h) :
#include <iostream>
void print_me() {
std::cout << "Hello World\n";
}

You have not included helloworld.h in helloworld.cpp. The following code should work:
#include <iostream>
#include "helloworld.h"
using namespace std;
int main() {
print_me();
system("pause");
return 0;
}
One thing to remember is from your compiler's point of view, there is no connection between the two files unless you specify it. The fact that both files have the same name does not have any significance for compiler.
Side note 1: Consider using include guards in your header files. For simple projects, it may not be obviously necessary but for larger projects, not using them can lead to annoying ambiguous compilation errors.
Side note 2: Implementing function bodies in header files is generally discouraged.

Related

C++ Does inlining a namespace implicitly inline its functions?

If I have a header with:
namespace outer {
inline namespace inner {
void func();
}
}
Then I can't define func() in a seperate .cpp file as that gives me a compile error:
- undefined reference to 'outer::inner::func()'
Just as if I declared the function inline. Is this correct? Does this mean that inlining a namespace implicitly inlines its functions. I tried looking at https://en.cppreference.com/w/cpp/language/namespace but couldn't find anywhere that this is explicitly stated.
EDIT 2:
Disregard, previous edit. I had failed to configue my cmake file properly and therefore was unable to compile the code. See answer for answer to original question. Thanks everyone!
EDIT:
Here is an example that I am unable to compile:
Test.h
namespace Core {
inline namespace TestNameSpace {
void write();
}
}
Test.cpp
#include <iostream>
#include "Test.h"
void Core::write() {
std::cout << "BAJS\n";
}
main.cpp
#include "Test.h"
int main() {
Core::write();
return 0;
}
I should note, #include "Test.h" is grayed out in my IDE in the Test.cpp file.
The simple answer is: no. You can absolutely define the functions in a separate cpp file. inline on a namespace basically makes it so that you don't need to specify the namespace name. For example, you can do outer::func() instead of outer::inner::func()
See [namespace.def]/5-7. There is no restrictions on where you must define the functions, and that it implicitly inlines them.
The error you are getting is in how you are compiling. Likely, you forgot to compile the .cpp file, or at least link it to where it is being called from.

Undefined reference to a defined method

So I was trying to access a method that is defined in another class and has the prototype in the header. I'm pretty positive I defined it but it keeps popping up undefined reference to SafeCracker.
Main.cpp
#include <iostream>
#include "mystuff.h"
using namespace std;
void BigDog(int KibblesCount);
int main()
{
cout << SafeCracker(1);
return 0;
}
mystuff.cpp
#include <iostream>
using namespace std;
string SafeCracker(int SafeID)
{
return "123456";
}
mystuff.h
using namespace std;
#ifndef MYSTUFF_H_INCLUDED
#define MYSTUFF_H_INCLUDED
string SafeCracker(int SafeID);
#endif // MYSTUFF_H_INCLUDED
Here it tells you that you have an undefined reference, so you don't really have a problem with the prototype.
Had you forgotten to include the header file that contains the prototype you would have gotten something like
main.cpp: In function ‘int main()’:
main.cpp:8:13: error: ‘SafeCracker’ was not declared in this scope
cout << SafeCracker(1);
Your undefined reference is a linker error. The most likely cause would be that you did not use mystuff.cpp when compiling
If you're compiling from the command line, you should give both files as parameters.
If you're using an IDE that calls the compiler, make sure that the file is part of the project.
For example in Code::Blocks right-click on the file name and go "add to project" (If I remember correctly)
It is also possible that you made a typo in the function declaration in mystuff.cpp (that doesn't seem to be the case here though)
Now there is one important thing about your code you should take note of:
It is very bad practice to put a using namespace in a header file.
using namespace std; in a .cpp source file is mostly up to you, and that using statement will only apply to that particular file.
But if you put it in a header file that is meant to be included through #include , the using there will be forced upon any code that includes it.
Here is an example:
main.cpp
#include <iostream>
// including mystuff.h to use that awesome SafeCracker()
#include "mystuff.h"
// I need to use an std::map (basically an associative array)
#include <map>
// the map of my game
class map
{
int tiles[10][10];
};
int main()
{
// The std map I need to use
std::map<int, int> mymappedcontainer;
// The map of my game I need to use
map mytiles;
// The reason why I need to include mystuff.h
cout << SafeCracker(1);
return 0;
}
Normally, my class map should not be a problem since the map I included from the standard library is inside the namespace std, so to use it you would need to go std::map.
The problem here is that, since mystuff.h has using namespace std; in it, the symbol map is already used, and that creates a conflict.
You do not now who will use your header files, or if you will use them again a long time from now, and maybe then you will want to use name that is already used in the std namespace.
I advise you to use std:: before things taken from the standard libraries instead (std::string instead of just string for example)
PS: In C++, "class" refers to a class data structure, and the functions you made here are not part of any class. You should say "defined in another file" or "defined in another translation unit" instead

Need assistance with code where it claims code not declared in this scope (C++)

I am practicing using multiple files for C++ in Code::Blocks. I have three files, two source files named main.cpp and Cat.cpp, and a header file named Cat.h. Though I declare a function designed to output text in Cat.h, the implementation in the main function returns the error "'speak' was not declared in this scope."
I tried researching the error, but that was tricky because it's such a general error that can occur for a wide variety of reasons. I tried carefully checking for syntax errors or improper #include statements in my code, but I can't find anything.
This is in my main.cpp file:
#include <iostream>
#include "Cat.cpp"
#include "Cat.h"
using namespace std;
int main()
{
speak();
return 0;
}
this is my Cat.h file:
#ifndef CAT_H_INCLUDED
#define CAT_H_INCLUDED
void speak();
#endif
and this is my Cat.cpp file:
#include <iostream>
#include "Cat.h"
using namespace std;
void speak(){
cout << "Meow!!" << endl;
}
I am expecting speak() to run, but the error says it is not declared in this scope.

Eclipse C++ multiple main error only when using multiple headers

I'm trying to learn how to utilize header files in C++ projects, so I made .cpp files containing simple functions to make sure I'm doing all the declaring and including correctly.
Everything worked fine when I only had one set of .cpp and .h files, but when I try to add more I get errors.
To start with, in my project I had:
helloworld.cpp
#include "helloworld.h"
#include <iostream>
#include <cstdio>
using namespace std;
int HelloWorld() {
puts("Hello, World!");
cout << "Hello, World!" << endl;
return 0;
}
helloworld.h
#ifndef HELLOWORLD_H_INCLUDED
#define HELLOWORLD_H_INCLUDED
int HelloWorld();
#endif /* HELLOWORLD_H_INCLUDED */
main.cpp
#include "helloworld.h"
#include <iostream>
using namespace std;
int main(){
HelloWorld();
return 0;
}
Which built with no errors and ran correctly.
Next I tried adding a second .cpp and .h file, which created building errors.
pointers.cpp
#include "pointers.h"
#include <iostream>
using namespace std;
int Pointers() {
int x = 1;
int *ptr_a = &x;
cout << *ptr_a << endl;
return 0;
}
pointers.h
#ifndef POINTERS_H_INCLUDED
#ifndef POINTERS_H_INCLUDED
int Pointers();
#endif /* POINTERS_H_INCLUDED */
and modified main.cpp:
#include "helloworld.h"
#include "pointers.h"
#include <iostream>
using namespace std;
int main(){
HelloWorld();
Pointers();
return 0;
}
Now when I try to build, I get an error saying there are multiple definitions of main -- one in main.cpp, and the other in pointers.cpp.
Even more oddly, if I make a new project and do the exact same thing but reverse the order in which I create the .cpp and .h files (i.e. pointers first then helloworld), it builds and runs correctly with just the pointers files but runs into the same error when adding helloworld files, saying that the multiple exceptions of main are in main.cpp and helloworld.cpp.
I figure it must have something to do with Eclipse itself, but I don't know what the exact issue is.
Does anyone know what might be going on?

C++ Namespace ofstream Won't Write

I'm working on making a game in C++. I have declared a Constant namespace used for global values that I need access to throughout the program. In there I have an ofstream for debugging purposes (yeah, I know it's not "constant" but it fits best there), which outputs only when it feels like it. I was able to make a small program demonstrating the problem. I apologize for it being spread across 4 files, but it is important, I promise.
main.cpp:
// Include necessary files
#include "test.h"
#include "constants.h"
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
// Start of program
Constant::outstream.open("test.txt");
// ...
// Do stuff
// Output debugging info
Test test;
test.print("Test", Constant::outstream);
// ...
// Do other stuff
// End of program
Constant::outstream.close();
return 0;
}
constants.h:
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
#include <fstream>
namespace Constant
{
static ofstream outstream;
}
#endif
test.h:
#ifndef _TEST_H
#define _TEST_H
#include <string>
#include <fstream>
#include "constants.h"
class Test
{
public:
void print(string str, ofstream& out);
};
#endif
test.cpp:
#include "test.h"
using namespace std;
void Test::print(string str, ofstream& out)
{
out << "out: " << str << endl << flush; // Works
Constant::outstream << "Constant::outstream: " << str << endl << flush; // Doesn't
}
In the test.cpp file, the out << ... line works as it should, while the Constant::outsream << ... line doesn't do anything even though I'm passing Constant::outstream as the out parameter! I don't see any reason why these two lines should be in any way different.
Before posting this, I tried putting test.cpp's code in test.h, just to have less files for the question, and was amazed to see it work. If I copy-paste the Test::print() function into test.h (whether inside or out of the class Test { ... }), then both output commands work correctly. the problem only occurs if Test::print()'s implementation is in a separate file.
It seems like any references to Constant::outstream simply don't work in class cpp files (no compile error, just nothing happens). It works in main.cpp and in class header files, but any class cpp file it seems not to. Unfortunately, this is a big program I'm writing so pretty much every class has its own cpp implementation file, and that's really the one place I need to use this ofstream. Does anyone know the reason for this?
Thanks in advance,
Doug
Constant::outstream has internal linkage, thus a separate instance is created for each translation unit. In short, Constant::outstream in test.cpp and main.cpp are two different variables.
§3.5.2 A name having namespace scope (3.3.6) has internal linkage if it is the name of
— a variable, function or function template that is explicitly declared static; or,
On the other hand, static class members would be visible throughout the program.
So, if you would write
struct Constant
{
static ofstream outstream;
}
instead of
namespace Constant
{
static ofstream outstream;
}
it would work.
However, note that the class must have external linkage; e.g. you should not put in in anonymous namespace.