C++ Class Method contains Undefined Reference to a Static Variable - c++

In C++, I'm trying to implement an enum to be accepted as a parameter in a method and consistently receive linking errors (undefined reference). Let me provide my header, implementation, and sample main execution. Also note that I am using a Makefile and can provide that if you believe the issue to be within the Makefile.
Header:
// Make sure definitions are only made once
//
#ifndef MYTEST_H
#define MYTEST_H
// System include files
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// Declare class definitions
//
class MyTest {
// Public data
//
public:
// Define debug_level choices
//
enum DBGL {FULL = 0, PARTIAL, BRIEF, NONE};
// Define a debug_level variable
//
static DBGL debug_level_d;
// Define public method set_debug that sets debug level to a specific value
//
bool set_debug(DBGL x_a);
// End of include file
//
#endif
Here is my implementation file 'mytest_00.cc'. Here, I am attempting to define an enum type "DBGL" as the debug level. And then I am trying to accept that as a parameter in the method 'set_debug'.
#include "mytest.h"
// Implementations of methods in MyTest
// Declare debug_level
//
static MyTest::DBGL debug_level_d = MyTest::FULL;
// Implement set_debug method to set the debug_level_d
// FULL = 0, PARTIAL = 1, BRIEF = 2, NONE = 3
//
bool MyTest::set_debug(MyTest::DBGL x_a) {
// Set debug_level_d to the argument provided
//
debug_level_d = x_a;
// exit gracefully
//
return true;
}
The goal is to test the class 'mytest' in the main function by executing something like:
MyTest Test;
Test.set_debug(FULL);
And this code would set the variable 'debug_level_d' as the parameter passed.
The error I receive upon compilation is as follows:
g++ -O2 -c mytest.cc -o mytest.o
g++ -O2 -c mytest_00.cc -o mytest_00.o
g++ -g -lm mytest.o mytest_00.o -o mytest.exe
mytest_00.o: In function `MyTest::set_debug(MyTest::DBGL)':
mytest_00.cc:(.text+0x12): undefined reference to `MyTest::debug_level_d'
collect2: error: ld returned 1 exit status
make: *** [mytest.exe] Error 1
Any help in understanding why this error is occurring would be greatly appreciated. I've been stuck on this for a day now. Please let me know if any details require further clarification.
Thank you.

You should not use the static keyword when defining the field in the .cpp file, only when declaring it in the class. Note in the code comments you have "declaring" and "defining" the wrong way round.
Additionally, when defining the member, you need to qualify it with the class name.
So the .cpp definition should be:
MyTest::DBGL MyTest::debug_level_d = MyTest::FULL;
By using the static keyword in the definition, you restrict it to internal linkage.
See: http://en.cppreference.com/w/cpp/language/static

Related

Error: Multiple definitions of function in C++ class [duplicate]

This question already has answers here:
Separating class code into a header and cpp file
(8 answers)
Closed 5 months ago.
I don't know how to add functions of a class outside its scope to it, use them in another class and then compile it.
MyMain.cpp
#include"MyClass.cpp"
int main(){
MyClass myClass;
myClass.run();
}
MyClass.cpp
#ifndef MYCLASS_CPP
#define MYCLASS_CPP
#include<iostream>
class MyClass {
private:
void usage();
public:
void run();
};
void MyClass::usage(){
std::cout << "usage called" << std::endl;
}
void MyClass::run(){
usage();
}
#endif
I try to compile it with:
g++ MyMain.cpp MyClass.cpp -o main
With that I get the following error message:
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::usage()':
MyClass.cpp:(.text+0x0): multiple definition of `MyClass::usage()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x0): first defined here
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::run()':
MyClass.cpp:(.text+0x38): multiple definition of `MyClass::run()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x38): first defined here
collect2: error: ld returned 1 exit status
If I have understood the concept correctly, the function headers within the class serve only as placeholders. The actual functionality is then "overwritten" by the external functions, which also contain a body.
And why does the error message say, that the function is already defined in the MyMain.cpp?
I have also seen that there are many similar questions here, but unfortunately I could not expand my understanding of the basic problem to solve it.
Is it possible that I am using the command to build the class with C++ incorrectly or that I can save the #include "MyClass.cpp"?
Kind regards
Several things wrong. here's the steps to put it right
Rename MyClass.cpp to MyClass.h.
Create a new empty file MyClass.cpp
Move the function definitions MyClass::usage() { .. } and MyClass::run() { .. } from MyClass.h to MyClass.cpp. You should probably also move #include <iostream> but this is not essential.
Add #include "MyClass.h" to MyClass.cpp
Change #include "MyClass.cpp" to #include "MyClass.h" in MyMain.cpp
Then build as you are doing now. That part is correct.
Essentially the technique is to separate your code into declarations and definitions. The declarations go into header files, which are included in the cpp files. The cpp files contain the definitions and are what you compile.

Calling function from different files in C++ error

I would like to use one function from Stats.cpp in Application.cpp. Here are my code snippets:
In Stats.h:
#ifndef STATS_H
#define STATS_H
class Stats
{
public:
void generateStat(int i);
};
#endif
In Stats.cpp:
#include Stats.h
void generateStat(int i)
{
//some process code here
}
In Application.cpp:
int main()
{
generateStat(10);
}
I get an "unresolved external symbol" error however I don't know what I else I would need to include in order for Application.cpp. Any thoughts?
In Stats.cpp
you need to define generateStat like following :
#include Stats.h
void Stats:: generateStat(int i) // Notice the syntax, use of :: operator
{
//some process code here
}
Then create object of class Stats, use it to call the public member function generateStat
Stats s;
s.generateStat( 10 ) ;
Build the application using :
g++ -o stats Stats.cpp Application.cpp -I.
generateStat is part of your Stats class. You need to instantiate a Stats object (along with the necessary includes for Stats.h in your main class)
For example,
Stats stat;
stat.generateStat(i);
Also, your function definition needs to include the class name Stats::generateStat.
The same error msg occured 2 weeks ago (at work).
At first glance --- Try:
void Stats::generateStat(int i) {
//some process code here }
The class name was missing. Hence, unresolved.
btw Concerning your header --- another issue, this #ifndef directive should not be necessary cause you should declare Stats only once in a namespace.
#ifndef CLASS_H
#define CLASS_H
#include "Class.h"
#endif
This is a generic example - Usable in cpp files.
EDIT: Now, I saw your invocation (main method in your case). You need an object instance to invoke your method.
Stats* stats = new Stats(); //add a default constructor if not done
stats->generateStat(77);
// any other stats stuff ......
// in posterior to the last use
delete(stats);
In your header:
Stats::Stats(){}; //with an empty body - no need to write it again in the cpp file

Error with multiple definitions of function

I am trying to relearn C++ after taking an intro course a few years ago and I’m having some basic problems. My current problem occurs when trying to use a friend function. Here is my code in 2 files.
First:
// fun.cpp
#include <iostream>
using namespace std;
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
cout<<"propa="<<propa<<endl<<"propb="<<propb<<endl;
}
};
void funct(){ // ERROR HERE
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
Second:
// mainfile.cpp
#include <iostream>
#include "fun.cpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
The error I am getting is "multiple definition of `funct()'". Am I using the wrong syntax when declaring it as a friend function?
Here is a highly simplified but hopefully relevant view of what happens when you build your code in C++.
C++ splits the load of generating machine executable code in following different phases -
Preprocessing - This is where any macros - #defines etc you might be using get expanded.
Compiling - Each cpp file along with all the #included files in that file directly or indirectly (together called a compilation unit) is converted into machine readable object code.
This is where C++ also checks that all functions defined (i.e. containing a body in { } e.g.
void Foo( int x){ return Boo(x); }) are referring to other functions in a valid manner.
The way it does that is by insisting that you provide at least a declaration of these other functions (e.g. void Boo(int); ) before you call it so it can check that you are calling it properly among other things. This can be done either directly in the cpp file where it is called or usually in an included header file.
Note that only the machine code that corresponds to functions defined in this cpp and included files gets built as the object (binary) version of this compilation unit (e.g. Foo) and not the ones that are merely declared (e.g. Boo).
Linking - This is the stage where C++ goes hunting for stuff declared and called in each compilation unit and links it to the places where it is getting called. Now if there was no definition found of this function the linker gives up and errors out. Similarly if it finds multiple definitions of the same function signature (essentially the name and parameter types it takes) it also errors out as it considers it ambiguous and doesn't want to pick one arbitrarily.
The latter is what is happening in your case. By doing a #include of the fun.cpp file, both fun.cpp and mainfile.cpp have a definition of funct() and the linker doesn't know which one to use in your program and is complaining about it.
The fix as Vaughn mentioned above is to not include the cpp file with the definition of funct() in mainfile.cpp and instead move the declaration of funct() in a separate header file and include that in mainline.cpp. This way the compiler will get the declaration of funct() to work with and the linker would get just one definition of funct() from fun.cpp and will use it with confidence.
The problem is that if you include fun.cpp in two places in your program, you will end up defining it twice, which isn't valid.
You don't want to include cpp files. You want to include header files.
The header file should just have the class definition. The corresponding cpp file, which you will compile separately, will have the function definition.
fun.hpp:
#include <iostream>
class classA {
friend void funct();
public:
classA(int a=1,int b=2):propa(a),propb(b){std::cout<<"constructor\n";}
private:
int propa;
int propb;
void outfun(){
std::cout<<"propa="<<propa<<endl<<"propb="<<propb<< std::endl;
}
};
fun.cpp:
#include "fun.hpp"
using namespace std;
void funct(){
cout<<"enter funct"<<endl;
classA tmp(1,2);
tmp.outfun();
cout<<"exit funct"<<endl;
}
mainfile.cpp:
#include <iostream>
#include "fun.hpp"
using namespace std;
int main(int nargin,char* varargin[]) {
cout<<"call funct"<<endl;
funct();
cout<<"exit main"<<endl;
return 0;
}
Note that it is generally recommended to avoid using namespace std in header files.
This problem happens because you are calling fun.cpp instead of fun.hpp. So c++ compiler finds func.cpp definition twice and throws this error.
Change line 3 of your main.cpp file, from #include "fun.cpp" to #include "fun.hpp" .
You have #include "fun.cpp" in mainfile.cpp so compiling with:
g++ -o hw1 mainfile.cpp
will work, however if you compile by linking these together like
g++ -g -std=c++11 -Wall -pedantic -c -o fun.o fun.cpp
g++ -g -std=c++11 -Wall -pedantic -c -o mainfile.o mainfile.cpp
As they mention above, adding #include "fun.hpp" will need to be done or it won't work. However, your case with the funct() function is slightly different than my problem.
I had this issue when doing a HW assignment and the autograder compiled by the lower bash recipe, yet locally it worked using the upper bash.

Error - invalid use of incomplete type / forward declaration of

My problem is pretty common I know but I've been searching and trying every solutions I found and still does not work. So any help would be greatly appreciated! =)
Thanks in advance!
I have this error at compilation :
g++ -ISFML/include -Iclasses/ -W -Wall -Werror -c -o classes/Object.o classes/Object.cpp
In file included from classes/Core.hh:18:0,
from classes/Object.hh:4,
from classes/Object.cpp:1:
classes/MapLink.hh:9:1: error: invalid use of incomplete type ‘struct Object’
classes/MapLink.hh:6:7: error: forward declaration of ‘struct Object’
In file included from classes/Core.hh:19:0,
from classes/Object.hh:4,
from classes/Object.cpp:1:
classes/Player.hh:9:1: error: invalid use of incomplete type ‘struct Object’
classes/MapLink.hh:6:7: error: forward declaration of ‘struct Object’
make: *** [classes/Object.o] Error 1
So basically, I've got a main containing (main.cpp)
#include "Core.hh"
int main(void)
{
...
}
Here's the header file containing all my includes (Core.hh)
#ifndef __CORE_HH__
# define __CORE_HH__
#include ...
#include "Object.hh"
#include "MapLink.hh"
#include "Player.hh"
class Core
{
...
};
#endif /* __CORE_HH__ */
And then the files that are causing me troubles (Object.hh)
#ifndef __OBJECT_HH__
# define __OBJECT_HH__
#include "Core.hh"
class Object
{
...
};
#endif /* __OBJECT_HH__ */
(MapLink.hh)
#ifndef __MAPLINK_H__
# define __MAPLINK_H__
#include "Core.hh"
class Object;
class MapLink : public Object
{
...
};
#endif /* __MAPLINK_H__ */
(Player.hh)
#ifndef __PLAYER_H__
# define __PLAYER_H__
#include "Core.hh"
class Object;
class Player : public Object
{
...
};
#endif /* __PLAYER_H__ */
Problem #1:
You must derive only from a fully declared class, otherwise the compiler wouldn't know what to do.
Remove the forward declaration class Object;.
Problem #2:
You have a circular dependency all over:
In "Core.hh" you include "Object.hh", "MapLink.hh" and "Player.hh".
In "Object.hh", "MapLink.hh" and "Player.hh" you include "Core.hh".
You need to make sure the each class fully includes the class that it inherits from.
I'm not sure how the classes interact with each other, you should provide that detail in the question.
My guess is that you need to modify your inclusions as follows:
Modify "MapLink.hh" and "PlayerLink.hh" so that they include "Object.hh", not "Core.hh"
Modify "Object.hh" so that it doesn't include "Core.hh".
Compiler must know full interface of a class for inheritance. In this case, the compiler couldn't see your object. It's necessary to include object.hh file in other files
Follow the includes:
Object.hh - __OBJECT_H__ is defined
Core.hh - __CORE_H__ is defined
MapLink.hh - includes Core.hh, but the content of that file isn't included because of step 2 and the #ifndef.
Player.hh - Same as step 3.
So MapLink.hh and Player.hh don't get to see the definition of Object before you try to inherit from it, and you can't inherit from a class that hasn't been fully defined.
To fix: specifically include the header of the class that you're inheriting from.
That is, add #include "Object.hh" to MapLink.hh and Player.hh.

C++ Template Class Problem

Hi everybody I just wanted to practice some c++ template but i get linker errors. Can anybody help me please?
Here is my code:
// File: MyClass.h
#ifndef _MYCLASS_H
#define _MYCLASS_H
template<class T> class MyClass {
T value;
public:
MyClass(T v);
~MyClass();
};
#endif // _MYCLASS_H
// File: MyClass.cpp
#include "MyClass.h"
template<class T> MyClass<T>::MyClass(T v) {
value = v;
}
template<class T> MyClass<T>::~MyClass() {
}
// File: main.cpp
#include "MyClass.h"
int main() {
MyClass<int> test(10);
return 0;
}
Here is command line output:
g++ main.cpp -c
g++ MyClass.cpp -c
g++ main.o MyClass.o -o Out
main.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `MyClass<int>::MyClass(int)'
main.cpp:(.text+0x2b): undefined reference to `MyClass<int>::~MyClass()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
As you can see I'm using Ubuntu 10.04 and GNU C++ Compiler.
Am I missing something in this code?
Thanks for replies. It works but isn't there a better way to protect the code?
For example what if I want to create a non-opensource library?!
I want to export the code to a static library. and link the library to other projects ...
You have to put full template into the header. Compiler needs to see the body of the template methods at the site of template instantiation - main.cpp in your case. See, for example, C++ FAQ.
You should put template classes and inline methods into header files. You can't seperate definition and implementation in their case.
#Nikolai N Fetissov has the right solution. I would add to this that a nice way to do this, if you want to keep the implementation and templated function definitions separate is that you can put the implementations into MyClass.hxx and include it at the end of your MyClass.h
// File: MyClass.h
#ifndef _MYCLASS_H
#define _MYCLASS_H
template<class T> class MyClass
{
T value;
public:
MyClass(T v);
~MyClass();
};
#include "MyClass.hxx" /// <--- like this
#endif // _MYCLASS_H
It's important to remember what a template is. It is a template for generating code if needed; it is not code itself.
So declaring a template class and writing implementations for those methods does not generate any object code for that class; it simply provides a template for doing so if necessary.
When a template class is instantiated with an actual argument, the compiler will generate the code from the template class. In order to do that, it needs to be able to see the the templates. But since you've only #includeed the .h file, and the implementation of the methods in in the .cpp file, the compiler won't be able to generate the object code for the function implementations. Then, when the linker looks for those definitions it won't find it.
All of this is a long-winded way of getting to the same result the other answers did -- you need to put the implementation in the header file with the class declaration. But it may help to know why that is.