I am writing a class and need to separate the declarations from the implementation, but I keep receiving "undefined reference" errors when compiling and linking my test program. It works fine when I include the implementation in the .h file, so I believe I am doing something wrong in there. I just can't figure out what.
Huge_Integer.h
#ifndef HUGE_INTEGER_H
#define HUGE_INTEGER_H
#include <vector>
#include <string>
using namespace std;
class Huge_Integer
{
public:
Huge_Integer();
Huge_Integer(string);
void input();
string output();
void add(Huge_Integer);
void subtract(Huge_Integer);
bool is_equal_to(Huge_Integer);
bool is_not_equal_to(Huge_Integer);
bool is_greater_than(Huge_Integer);
bool is_less_than(Huge_Integer);
bool is_greater_than_or_equal_to(Huge_Integer);
bool is_less_than_or_equal_to(Huge_Integer);
private:
vector<int> value;
};
#endif
Huge_Integer.cpp
#include<vector>
#include<string>
#include<iostream>
#include "Huge_Integer.h"
using namespace std;
// all stubs for now...
Huge_Integer::Huge_Integer()
{
cout << "object created\n";
}
Huge_Integer::Huge_Integer(string s)
{
cout << "object created\n";
}
//etc...
It also works if I put #include "Huge_Integer.cpp" in my test file, but I shouldn't have to do that, right?
I am using MinGW.
Thanks in advance!
Edit: Added stubs from my .cpp file
Sounds like a linking issue.
What that means is that you have to compile your class first -- this will create a compiled object file.
Then compile the main program while passing in this compiled version of the class.
Like this:
g++ -c huge_integer.cpp
g++ main.cpp huge_integer.o
Substitute your mingw command for g++ if it is different.
Not related to linking, but you are referring to Huge_Integer inside the class declaration itself.
At least with g++, you should add a forward declaration before so that Huge_Integer has meaning inside the class declaration thus:
class Huge_Integer; // forward declaration
class Huge_Integer {
Huge_Integer();
// etc...
void add(Huge_Integer);
Note: I don´t have comment privileges, so I had to type in the answer box.
Related
I've been searching through questions on this for hours, and it just isn't working for some reason, so sorry if there's already an answer and I just didn't understand it.
I'm doing a course on C++, and I've gotten to classes. As practice, he started by just calling a simple function that was defined in a separate .cpp file to show how a class would work later on. See code below:
//main.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
int main() {
speak();
return 0;
}
============================
//Cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
void speak() {
cout << "Meow" << endl;
}
================================
//Cat.h
#ifndef CAT_H_
#define CAT_H_
void speak();
#endif //CAT_H_
I've triple checked everything I could think of. They're in the same directory and I'm cross-referencing everything exactly as he did. I expect it to output "Meow" in the console, but if I call the speak() function in main.cpp, I still just get an empty function, despite it being defined in class.cpp. I don't know what I'm missing, and it's quite frustrating. Is is because of my compiler? I'm using Visual Studio IDE.
Edits: Used the wrong commented name
I'm using the built-in Visual Studio IDE's "Build" and "Compile" options. I'm not running the compilation using Linux commands or anything else.
#273K Here is the screenshot of my 3 VS files:
https://i.stack.imgur.com/9tbw8.png
The problem is that you are including Cat.h but named your header class.h instead of Cat.h.
To solve this rename the files from class.h and class.cpp to Cat.h and Cat.cpp respectively, as shown below
Cat.h
#ifndef CAT_H_
#define CAT_H_
void speak();
#endif //CAT_H_
Cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
void speak() {
cout << "Meow" << endl;
}
main.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
int main() {
speak();
return 0;
}
Working demo
Thanks to #273K for the solution:
In the screenshot, the wrong project was "selected" in the solution explorer, so it was running the wrong project code.
I fixed it by right-clicking the project I wanted and clicking "Set as StartUp Project"
Before: https://i.stack.imgur.com/na0nF.png
After: https://i.stack.imgur.com/EJMLq.png
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.
Trivial as it ought to be, I just cannot figure out how to separate my source code into different files.
My code compiles and executes just fine when it is written as a single source file:
#include <iostream>
using namespace std;
class Greeter{
public:
void greet();
};
void Greeter::greet(){
cout << "Hello World!";
}
int main(){
Greeter greeter;
greeter.greet();
return 0;
}
But try as I might, separating the code into separate source files:
Greeter.h
#include <iostream>
using namespace std;
class Greeter{
public:
Greeter();
void greet();
};
Greeter.cxx
#include <iostream>
#include "Greeter.h"
using namespace std;
void Greeter::greet(){
cout << "Hello World!";
}
main.cxx
#include <iostream>
#include "Greeter.h"
using namespace std;
int main(){
Greeter greeter;
greeter.greet();
return 0;
}
always results in a compilation error:
main.cxx:(.text+0x16): undefined reference to `Greeter::Greeter()'
It is unclear whether the comments solved your problem. In separating your source into a header and multiple sources, your primary problem evidenced by the error is that you include an incomplete constructor for class Greeter in Greeter.h. Specifically, you fail to include "an empty parameter list" to complete the constructor, e.g.
Greeter() {}; /* default construct */
See cppreference - Default constructors
The next issue you should avoid is including using namespace std; in the header file. See “using namespace” in c++ headers. Instead, simply make your call to cout, std::cout and eliminate the need to include the namespace altogether.
Next, while iostream has proper header guards, you only need to include it in Greeter.cpp (that is the only source making use of an iostream function). You should also include header guards in your Greeter.h to prevent multiple inclusions during compilation. Simply create a #define and check whether or not that is already defined within the header, e.g.
greeter.h
#ifndef my_class_greeter_h
#define my_class_greeter_h 1
class Greeter {
public:
Greeter() {}; /* default construct */
void greet();
};
#endif
Now every file that includes greeter.h will avoid including it again if my_class_greeter_h is already defined.
greeter.cpp
Your source file with your class function definition is the only source that relies on an iostream call, and is the only file that requires #include <iostream>, e.g.
#include <iostream>
#include "greeter.h"
void Greeter::greet(){
std::cout << "Hello World!\n";
}
main.cpp
You main.cpp source file need only include your header containing the class definition, e.g.
#include "greeter.h"
int main (void) {
Greeter greeter; /* instantiate greeter */
greeter.greet(); /* call greet() */
return 0;
}
Both Sources Must Be Compiled
Compiling the separate source files requires that both main.cpp and greeter.cpp be compiled (either compiling greeter.cpp to object or by simply including both .cpp files in your compile string).
Compiling With gcc/clang
$ g++ -Wall -Wextra -pedantic -std=c++11 -Ofast -o main main.cpp greeter.cpp
Compiling With VS (cl.exe)
> cl /nologo /W3 /Ox /EHsc /Femain /TP main.cpp greeter.cpp
(do not accept code until it compiles without warning)
Example Use/Output
In either case, the output is as expected:
$ ./main
Hello World!
Look things over and let me know if you have further questions.
Hi I was just trying to learn separate Classes in C++. I don't know why my code is not working.
So here is the main file code
#include <iostream>
#include "Number.h"
using namespace std;
int main()
{
Number key;
key.setNumber(200);
cout<<key.getNumber();
return 0;
}
Here is the Class cpp functions file code
#include "Number.h"
#include <iostream>
using namespace std;
void Number::setNumber(int transfernumber)
{
privatenumber = transfernumber;
}
int Number::getNumber()
{
return privatenumber;
}
And here is the header file
#ifndef NUMBER_H
#define NUMBER_H
class Number
{
public:
Number();
void setNumber(int transfernumber);
int getNumber();
private:
int privatenumber;
};
#endif // NUMBER_H
Thanks
In your cpp file you need to define the default constructor for the Number class. For example:
Number::Number() : privatenumber(0) {}
I have test your example. The error happened for the main.cpp cannot found the number.cpp. You have three ways to solve it:
write your main() to the number.cpp, not a solo file.
complie the main.cpp with the linux command gcc or write a Makefile, instead of using codeblocks.
If you want to use the codeblocks for compiling, you should create a project, and then add your three files to the project. Now compile the main.cpp.
Use the three ways above, I think you will compile successfully.
BTW, you should add the Number::Number() 's implementation.
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.