Why can't linker see my (definitely defined) externals? - c++

I have a class with a header and a .cpp file. I declare my functions in the header, and define them in the .cpp file, as you would.
Header:
#pragma once
// my #includes
class CDNAGenerator
{
private:
// stuff
public:
CDNAGenerator(int, int);
~CDNAGenerator();
void FilterMeasurementsForOutliers(std::vector<double>& measurement_values);
// plenty more things
};
CPP:
CDNAGenerator::CDNAGenerator( int genes, int chromosomes )
{
// constructor code
}
void CDNAGenerator::FilterMeasurementsForOutliers(std::vector<double>& measurement_values)
{
// function code
}
Then, from a separate project in the same solution I reference the .h file (but not the .cpp - that seems to lead to multiple definition errors):
#include "..\CalibrationTool\DNAGenerator.h"
And call those functions:
CDNAGenerator* dnaGenerator = new CDNAGenerator(30, 0);
dnaGenerator->FilterMeasurementsForOutliers(values);
But I get unresolved external errors for CDNAGenerator::CDNAGenerator(int, int) and for CDNAGenerator::FilterMeasurementsForOutliers(class std::vector > &)
I thought that I had hooked everything up correctly, so can anyone suggest why I would be getting this linker error?

Add the CPP file to the project

What compiler are you using? Gcc (mingw) does'n supprort #pragma once Use code guards to avoid 'multiple definitions'.
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
...
}
#endif

Related

How to use the same header files in different classes to avoid "use of undefined type"

I'm currently writing a simple game with a 2D library and as C++ is a new language to me and as Java is my first fluent programming language, perhaps some bad habits are flowing through to this language that I don't fully understand. I have never had problems doing this in Java but in C++ it causes a ton of errors. As I don't want everything crammed into one class/header file, I've decided to split them up into packages and different classes, but I can't seem to do this without includng the same header files in different places. Here's an example.
Project.h
#ifndef PROJECT_H
#define PROJECT_H
#include "UIManager.h"//this is causing the error, when this, and the class instance is removed the program compiles and runs fine without error
using namespace gamelib;
class Project : public Game {
public:
Project(int argc, char* argv[]);
~Project();
void Update(int elapsed);
void Draw(int elapsed);
void Load();
/*Background*/
Texture * background;
Rectangle* backgroundRectangle;
UIManager ui;
};
#endif
UIManager.cpp
#include "UIManager.h"
void UIManager::load() {
startMenuBackground = new Texture();
startMenuBackground->Load("Sprites/Interface/Transparency.png", false);
startMenuRectangle = new Rectangle(0.0f, 0.0f, Graphics::GetWidth() / 2, Graphics::GetHeight() / 2);
}
UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H
#include "Project.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif
Now I need all of these includes so I can store the necessary textures, and the Texture and Rectangle come from the API that is being used as a namespace in Project.h
I also need a class instance in Project.h, UIManager ui; So i can use this in the Project.cpp file to call methods
How can I get around this without getting all these errors?
If I understand your problem correctly, you want to avoid including header files multiple times. In that case, what you should do is using Include guards. Which makes sure that the header is included once. Optionally you can use #pragma once at the top of your file but that's another discussion.
Example:
#ifndef UIMANAGER_H // you may choose another name than "UIMANAGER_H"
#define UIMANAGER_H
// Your header file code and includes here.
// Do this for your header files.
#endif
Now, do the same for the other header file but instead naming the macro PROJECT_H or similar.
A good practice is to add in the beginning and in the end of the .h files:
#ifndef FILENAME_H
#define FILENAME_H
//Your code here
#endif
Where FILENAME_H is unique for each .h file.
Those are compiler predirectives, which are not included in the executable, but changes the way that the compiler acts.
Adding those, the compiler won't add the same file twice for the same file. If it's already loaded, it won't load it.
Take in account than in C++, header files are parsed independently on each file of the project.
Typically, the fix would be to change your code to this...
#ifndef UIManager_H
#define UIManager_H
// It's pretty normal to put each class in its own header file.
#include "Texture.h"
#include "Rectangle.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
Since you never instantiate either object though, you don't strictly need a full header.
#ifndef UIManager_H
#define UIManager_H
// Since we only use pointers to the classes, we can forward declare the classes
class Texture;
class Rectangle;
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
You can use the macros #ifndef and #define. This is a common pattern. For example, in your UIManager.h file, have the following:
#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__
#include "Project.h"
//Rest of UIManager class definition
#endif
In you Project.h file, have the following:
#ifndef __PROJECT_H__
#define __PROJECT_H__
#include "UIManager.h"
//Rest of Project class definition
#endif
This allows the compiler to compile without errors when it sees circular includes. But it's more preferable to use class forward declaration if possible, but this is a completely different topic.
The macro names __UI_MANAGER_H__ and __PROJECT_H__ are purely randomly chosen. You can choose to use a different naming convention.

Preventing "already defined" error for class implementation in header file

I want to include the definition and implementation of a C++ class in a header file.
I'm creating a library that need to be C-compatible. The .h file defines a C++ class that can be subclassed for easy C++-style access to the library. It is internally used in the library as well.
As the header file is imported into several subclasses, I always get the "multiple definition" error. Because the class definition should be importable for users of the library, I do not want to move the implementation in a separate cpp file.
Do you have any idea how this problem can be solved?
simplified example:
//library:
typedef struct IFoo{
virtual void foo = 0;
};
void library_fun_a(IFoo*);
void library_fun_b(IFoo*);
//header file
#pragma once
class FooWrapper : public IFoo{
virtual void foo() override;
};
void FooWrapper::foo(){
//some magic here
}
[Edit] Using include guards doesn't help to stop the compile from including the implementation in all object files and therefore the linker to encounter the "multiple definition" error.
You must use include guards which are essentially just macros that determine if the compiler has already included the interface or whatever contents are in the header file.
For example
#ifndef FOO_WRAPPER_H
#define FOO_WRAPPER_H
// header contents here ...
#endif // !FOO_WRAPPER_H
If you're using a Microsoft compiler, you can use the directive #pragma once at the top of the header file. Note that this breaks compatibility with other compilers.
You can easily solve your multiple defintion problem when you inline your code correctly:
class FooWrapper : public IFoo {
virtual void foo() override {
//some magic here
}
};

C++ static bool variable

I can't understand something that causes LNK2005 errors that I've encountered.
Assume that you have a class A:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
bool A::m_someVar = false;
#endif
File A.cpp:
#include "A.h"
void A::foo(){
m_someVar = true;
}
The code above causes a LNK 2005 however the following code doesn't:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
#endif
File A.cpp:
#include "A.h"
bool A::m_someVar = false;
void A::foo(){
m_someVar = true;
}
Can someone explain why is this happening even though I have include guards? Should I also add #pragma once?
Thanks in advance.
EDIT: here's the compilation error:
"error LNK2005: "private: static bool GameManager::m_isGameOver" (?m_isGameOver#GameManager##0_NA) already defined in Execution.obj"
include guards(both #ifndef and #pragma) doesn't work across compilation units, which is one of the reasons you should never ever ever define anything in a header file, only declare them. Except for templates of course.
A compilation unit is one .cpp-file and all included headers. Each .cpp create an object file containing a middle stage binary representation of the code, this is the compilation stage. These object files are then linked together in the linking stage. Since each .cpp is handled separately in c++ if you have "float foo;" in header.hpp and both a.cpp and b.cpp include header.hpp, how would the compiler know which foo you mean when running the application?
A "static" variable inside a class declaration is actually a declaration for an extern variable that is in the scope of that class. Like every extern variable, it needs a definition in exactly one source file. Otherwise, the linker will complain about it.
You probably include the .h file from more than one source file, so you have more than one definition.

Solution to Multiple definition in C++

guys, this is my first question in StackOverflow so forgive me if make any mistake.
I am writing a small project which contains 2 source files and 3 header files.
// some_template_functions.h
#ifndef SOME_TEMPLATE_FUNCTION_H
#define SOME_TEMPLATE_FUNCTION_H
template <typename T>
int getvalue(string line, string key, T & val)
{
// method to get value (all the types except string) from line using key
}
template <>
int getvalue<string>(string line, string key, string &val)
{
// method to get some string from line using key, similar to getvale<int>
// but with slight difference to handle some special characters
}
#endif
//myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include "some_template_functions.h"
class MYCLASS
{
//declarations of constructors, member functions and members
double member_double;
string member_string;
}
#endif
//myclass.cpp
#include "myclass.h"
MYCLASS:MYCLASS()
{
// for each member
// using "getvalue" defined in "SOME_TEMPLATE_FUNCTION.H" to get the values
getvalue(line, key, member_double);
getvalue(line, key, member_string);
}
//main.cpp
#include "myclass.h"
#include "some_template_functions.h"
int main()
{
myclass A;
int some_value;
getvalue(line, key, value);
return 0;
}
I have no problem compiling the main.o and myclass.o but it is just when I was trying to link the two object files I got error message like:
myclass.cpp: multiple definition of int getvalue<std::basic_string><char, std::char_traits<char>, ...> and etc.
/tmp/cc22zEow.o:main.cpp: first defined here
collect2: ld returned 1 exit status
I know the reason probably is because I am including "some_template_function.h" in both myclass.h and main.cpp, each myclass.o and main.o is going to have its own definition of getvalue which is causing the problem. If I change
#include "some_template_functions.h"
to
#ifndef SOME_TEMPLATE_FUNCTIONS_H
#define SOME_TEMPLATE_FUNCTIONS_H
#endif
the constructors of MYCLASS is not goint to work.
I plan to expand the "some_template_functions.h" and its .cpp file in the future so if possible I would like to keep them separated from the other files. And because the way I am declaring function "getvalue" my attempt to move its definition to .cpp file was not working out for me very well.
I've tried to solve this problem for days but since I just start to learn C++ so far I could not get this right. So please, any suggestions will be appreciated! Thanks in advance!
The specialization of getvalue<std::string>(...) isn't a template and, thus, not implicitly inline. If you want to define this function in a header, e.g., because it is close to trivial and should be inlined, you'll need to mark it explicitly as inline. If the function does anything non-trivial it may be worth merely declaring the specialization in the header and defining it in a suitable translation unit.

Visual C++ Linking LNK2019 Error with a Precompiled Header

I had a very weird problem with precompile header. The linker generates LNK2019: unresolved external symbol error when I implement method in .cpp file. However, the program could be compiled if I implement method in .h file. I happened to find out a solution but I have no idea about the root cause of this error.
My project structure looks like this
Solution
->project 1
->project 2
Project 1 has 3 files. A.h, A.cpp and stdafx.h
file A.h
#pragma once
class A
{
public:
int num;
A();
};
file A.cpp
#include "stdafx.h"
A::A()
{
num = 2;
}
file stdafx.h
...
#include "A.h"
...
In project 2. I want to use A class.
file whatever.cpp
#include "stdafx.h"
#include "../Project1/A.h"
...
A* a_obj = new A();
...
In compile time, the linker reports unresolved external symbol error for the A construction function. If I implement the constructor in A.h file. the project2 could be successful complied. I want to know, why can not put the implementation in A.cpp file? What is the right way to organize precompile header?
Thank you
Project 2 does not include the definition of the A constructor - one way to give it visibility of this is to include the definition in the header file (which you did).
Another way would be to include the A.cpp file in project 2.
A third way would be to export the A class, or the A constructor using a .def file or using the dllexport directive.
Put this in the precompiled header file:
// set up export import macros for client project use
// define the symbol "PROJ1" before including this file in project 1 only
// leave it undefined for other projects
#ifdef PROJ1
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP __declspec(dllimport)
#endif
Then declare the A class in the A header:
DLLEXP class A
{
public:
A();
...
};
Or:
class A
{
public:
DLLEXP A();
...
};