my code is:
#pragma once
#include "stdafx.h"
#include <vector>
#include "field.h"
class output
{
void putAtLocation(COORD, char chIcon); //currently this outputs to console
static std::vector<COORD> m_vsOutputBuffer;
public:
output(void);
static void addToken(COORD);
void drawTokens();
~output(void);
};
and the linker error is:
output.obj : error LNK2001: unresolved external symbol "private: static class std::vector<struct _COORD,class std::allocator<struct _COORD> > output::m_vsOutputBuffer" (?m_vsOutputBuffer#output##0V?$vector#U_COORD##V?$allocator#U_COORD###std###std##A)
this must be the problem line:
static std::vector<COORD> m_vsOutputBuffer;
I've been at this for hours stuck. I finally noticed that changing COORD to int causes the linker error to go away. I've read that it's(linker errors) are usually caused by dependency issues. But here it just changing a TYPE. I've also read it can be caused by using a function in a way it wasn't supposed to be. I figure it has to be the way is handling COORDs; or something about COORDS is forward declared, or referenced in output.cpp properly.
Edit:
all changing to int did was make compiler errors that caused it never to hit the linker. now I am back to nothing
and the cpp file:
#include "stdafx.h"
#include "output.h"
#include <vector>
static std::vector<int> m_vsOutputBuffer;
output::output(void)
{
}
void output::addToken(COORD sCoordinate) //mark a coord in the buffer as needing refreshed
{
m_vsOutputBuffer.push_back(sCoordinate);
}
void output::drawTokens() //release the outputbuffer the the output window
{
for (unsigned int iii = 0; iii < m_vsOutputBuffer.size(); iii++)
{
putAtLocation(m_vsOutputBuffer[iii], field::checkHit( m_vsOutputBuffer[iii] ) );
}
}
void output::putAtLocation(COORD sCoordinate, char chIcon) //outputs a single character to the console
{
DWORD dwNumWritten = 0;
LPDWORD lpdNumWritten = &dwNumWritten;
WriteConsoleOutputCharacter(
GetStdHandle( STD_OUTPUT_HANDLE ), //***repeatedly getting this handle may end up a bottleneck
LPCTSTR(&chIcon),
1,
sCoordinate,
lpdNumWritten
);
}
output::~output(void)
{
}
also I found this: http://www.cplusplus.com/forum/general/6111/
so I tried moving the static statement to the cpp file and it compiled and ran. but not its not a member variable. So I Need to somehow forward declare the vector.(before the declaration was also creating the static object in the header file.
you need this line in your .cpp file:
std::vector<COORD> output::m_vsOutputBuffer;
(Note the absence of static and the scope output::)
This is the actual definition of the member variable. What you have in the class (.h) is only the declaration.
Without this the static variable output:m_vsOutputBuffer does not exist and the linker rightfully complains that it can't find it.
Coord is defined in windows.h header... Look into stdafx.h if there is something like
#include <windows.h>.
Other than that I tried to copy your code add this header and compile it.. went smooth
To edited version:
You probably forgot to change
static std::vector<int> m_vsOutputBuffer;
back to
static std::vector<COORD> m_vsOutputBuffer;
But I assume you had it that way before.. Second thing is that you don't have to include the same headers in header and cpp file but this is not causing it.. It is the line in cpp file with
static std::vector<COORD> m_vsOutputBuffer;
change it just to:
std::vector<COORD> output::m_vsOutputBuffer;
You can read on why in this text:
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr038.htm
Simply said you need do define not just declare.
Related
There are a lot of similar questions on Stack Overflow, regarding this topic.
I am creating a project with multiple files (.cpp and .h). I am getting the error:
C2011: 'Render': 'class' type redefinition
I have read about it. Some people are saying use guards, so I am using #pragma once on all header files. Some people say the header is being included multiple times, but the guards will prevent that. So what am I doing wrong?
Code:
Cubes.h
#pragma once
char orientation(int sides, int hV);
std::vector<char> visOrd(std::string *xOrd, int *pov, int ord);
std::vector<int> convertColour(std::vector<std::string> rlBoxCol);
std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot);
class Render
{
private:
std::vector<float> rot;
std::vector<int> boxCoords;
std::vector<std::string> rlBoxCol;
int gridSize;
int cubeSize;
std::vector<int> offset;
public:
Render();
void setRotation(std::vector<float> setRot);
std::vector<float> getRotation();
void setCoordinates(std::vector<int> setBoxCoords);
std::vector<int> getCoordinates();
void setColours(std::vector<std::string> setRlBoxCol);
std::vector<std::string> getColours();
void setSizeOfGrid(int setGridSize);
int getSizeOfGrid();
void setSizeOfCubes(int setCubeSize);
int getSizeOfCubes();
void setOffset(std::vector<int> setOffset);
std::vector<int> getOffset();
void display();
};
Cubes.cpp
#include "Cubes.h"
#include "Global.h"
char orientation(int sides, int hV)
{
// Code
}
std::vector<char> visOrd(std::string *xOrd, int *pov, int ord)
{
// Code
}
std::vector<int> convertColour(std::vector<std::string> rlBoxCol)
{
// Code
}
std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot)
{
// Code
}
Render::Render()
{
this->rot;
this->boxCoords;
this->rlBoxCol;
this->gridSize;
this->cubeSize;
this->offset;
}
void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
rot = setRot;
}
std::vector<float> Render::getRotation()
{ // Get rotation
return rot;
}
void Render::setCoordinates(std::vector<int> setBoxCoords)
{
boxCoords = setBoxCoords;
}
std::vector<int> Render::getCoordinates()
{
return boxCoords;
}
void Render::setColours(std::vector<std::string> setRlBoxCol)
{
rlBoxCol = setRlBoxCol;
}
std::vector<std::string> Render::getColours()
{
return rlBoxCol;
}
void Render::setSizeOfGrid(int setGridSize)
{
gridSize = setGridSize;
}
int Render::getSizeOfGrid()
{
return gridSize;
}
void Render::setSizeOfCubes(int setCubeSize)
{
cubeSize = setCubeSize;
}
int Render::getSizeOfCubes()
{
return cubeSize;
}
void Render::setOffset(std::vector<int> setOffset)
{
offset = setOffset;
}
std::vector<int> Render::getOffset()
{
return offset;
}
void Render::display()
{
// Drawing code
}
EDIT:
I have now changed the code in ways you said. Now I am getting errors LNK2005 and LNK1169. What's gone wrong now?
EDIT 2: (Errors)
LNK2005
"class sf::RenderWindow Window" (?Window##3VRenderWindow#sf##A) already defined in Cubes.obj
C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1
.
LNK2005
"class std::basic_string,class std::allocator > status" (?status##3V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) already defined in Cubes.obj
C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1
.
LNK1169
one or more multiply defined symbols found
C:\Users\George\Documents\C++\Projects\Don't fall\Debug\Don't fall.exe 1
Global.h:
#pragma once
#include <SFML\Graphics.hpp>
// This is where all my global variables will be
extern sf::RenderWindow Window(sf::VideoMode(500, 500), "Maximize window to play the game");
extern std::string status = "NULL";
Your Cubes.cpp does redefine the class Render. In general the .h file has the class prototype and the .cpp defines the methods.
Try adding this to the top of the Cubes.cpp:
#include "Cubes.h"
removing this from the top of Cubes.cpp:
class Render
{
private:
std::vector<float> rot;
std::vector<int> boxCoords;
std::vector<std::string> rlBoxCol;
int gridSize;
int cubeSize;
std::vector<int> offset;
public:
and removing this from the bottom:
};
This is not how you provide the implementation of a class in C++. The keyword class defines the class, which is what you have in your header (.h file). In the .cpp file you wish to implement the methods which you defined in your header file, so you should not redefine the entire class. Rather, you need to provide implementations for the methods (member functions) of the class, like so:
void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
rot = setRot;
}
std::vector<float> Render::getRotation()
{ // Get rotation
return rot;
}
Notice the prefix Render::? This is how you indicate that you are providing an implementation for the function setRotation of the class Render. Just add the function implementation like this in your cpp, do not nest them within a class, do not include any fields (the member fields have already been defined in the header, they are done).
Update:
OK, so according to the updated answer your linker error refers to the instances sf::RenderWindow Window and std::string status; this error occurs when linking main.obj (from main.cpp?) with Cubes.obj. The error is telling you that both main.obj and Cubes.obj define these variables.
I recommend that you read about "Compilation Units" in C++ and difference between declaration and definition of a symbol; but to give a very brief summary:
Essentially, the compiler runs on a single "compilation unit"; you can think of it as a single file. What the #include-statement does is basically copy/paste the content of the included file into the compilation unit. So when you compile Cubes.cpp, it will go through all of the nested includes until it has generated one huge cpp-file with everything included. Then it will build this into an .obj file. Then you do the same thing with main.cpp, and any other .cpp files you might have. Finally, the linker will attempt to link these object files together to produce the final result.
Now, if the linker finds duplicate definitions when linking two objects you will get an error. So you cannot have two global variables with the same name! If both Cubes.cpp and main.cpp include global.h, then both compilation units contain global variable definitions Window and status. This is causing your linker error.
This is why you put a declaration in the header (since it is included in multiple compilation units), and the definition in the source file (typically not included elsewhere). You build the source file to produce the only object file containing the definition; all other object files only reference the declaration. The linker can then link those references to the definition found in one the object files.
So you want to declare the variables in the header, and move the definition somewhere else. For instance, to main.cpp; but that depends entirely on the rest of your application and what you are trying to achieve. Outside the scope of the question.
For the life of me I cannot figure out what is causing this... I keep getting unresolved external symbol error. However, if I put an empty definition in the header file it compiles correctly.
WINMAIN.CPP
#include "FILE_XXX.H"
int WINMAIN WinMain(...)
{
EnableOpenTest(); // call like this
return 0;
}
FILE_WORKS_CORRECTLY.H
#ifndef _FILE_WORKS_CORRECTLY_
#define _FILE_WORKS_CORRECTLY_
void EnableOpenTest() { }
#endif
However, when I do something like this (correctly), it does not work and I get a compile-time error.
FILE_DOES_NOT_WORK_CORRECTLY.H
#ifndef _FILE_DOES_NOT_WORK_CORRECTLY_
#define _FILE_DOES_NOT_WORK_CORRECTLY_
void EnableOpenTest();
#endif
FILE_DOES_NOT_WORK_CORRECTLY.CPP
#include "FILE_DOES_NOT_WORK_CORRECTLY.H"
void EnableOpenTest() { /* do work here */ }
UPDATE:
Upon further investigation, I found the issue has to do with me having multiple projects in the same solution. I then try to reference a function in one project from another project. Obviously I'm doing this incorrectly.
The only mistake i see is that in the cpp file you need to include the return type as well. It should be
void EnableOpenTest()
{
//Enter Code Here
}
Inside of FILE_DOES_NOT_WORK_CORRECTLY.CPP:
EnableOpenTest(){ /* do work here */ }
must be
void EnableOpenTest(){ /* do work here */ }
Looks like your compiler sets the missing return type to int instead of yelling at you with a error message.
You should turn on compiler warnings, it would allow you to notice such errors very quickly.
Also, inside of FILE_WORKS_CORRECTLY.H you have another error:
void EnableOpenTest() { }
must be
inline void EnableOpenTest() { }
Otherwise it will trigger a error message if this header is included twice (i.e. in more that one .cpp file).
Solved it!
Additional projects needed to be static library (main project .exe)
Added References of library projects to main project
Obviously the file structure caused a lot of these issues.
What is the correct way to use inheritance among multiple files?
I am new to C++, and I am trying to create a class for all my GDI+ related functions which I'm gonna use in my separate cpp files. I have tried several approaches and to be able to find the problem more easily I got to trying with empty constructor.
I get LNK2019 with this code (I took away parts which are unrelated to the issue, only what is related to WndFuncs class was left):
Header of functions file:
#ifndef WNDFUNCS_H
#define WNDFUNCS_H
class WndFuncs
{
private:
public:
WndFuncs(); //declaration
};
#endif
The file itself:
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#include <winuser.h>
#include <gdiplus.h>
#include "WndFuncs.h"
WndFuncs::WndFuncs() //definition
{
}
The header of class that tries to inherit the class:
#ifndef SEARCHEDITBOX_H
#define SEARCHEDITBOX_H
class SearchEditBox : public WndFuncs
{
private:
WndFuncs b;
SearchEditBox();
public:
~SearchEditBox();
static SearchEditBox* CreateEditBox(HINSTANCE hInst, HWND hwnd, int pos_x, int pos_y, int width, int height, WndCols const* p_wndCols);
#endif
The the class file:
#include "stdafx.h"
#include "WndCols.h"
#include <windows.h>
#include "WndFuncs.h"
#include "SearchEditBox.h"
SearchEditBox::SearchEditBox()
: b()
{
}
SearchEditBox::~SearchEditBox()
{
if (editBox)
DestroyWindow(editBox);
}
SearchEditBox* SearchEditBox::CreateEditBox(HINSTANCE hInst, HWND hwnd, int pos_x, int pos_y, int width, int height, WndCols const* p_wndCols)
{
SearchEditBox *p_SearchEditBox = new SearchEditBox; //allocating dynamic memory for class (which by itself is declared as pointer)
return p_SearchEditBox;
}
The error is:
LNK2019 unresolved external symbol "public: __thiscall
WndFuncs::WndFuncs(void)" (??0WndFuncs##QAE#XZ) referenced in function
"private: __thiscall SearchEditBox::SearchEditBox(void)"
(??0SearchEditBox##AAE#XZ)
I have read the explanation and all the points on the MSDN page (even tried putting "__cdecl" into the function declaration), I am sure the function is declared AND defined (in the class files; I also tried with const int x thinking that the problem may be in empty constructor), so the WndFuncs file should be fine.
I have read this and my assumption is that I declare the class in the wrong way in the inheriting file (and the linker thus can't link to correct functions in WndFuncs class), but even when I am trying to do everything as described in here it does not help either. I am not using any virtual members so the problem should not be related to that (as pointed out on that page).
When I add destructor to the WndFuncs class I get 2 LNK2019 errors, so the problem should not be related to that also. I also have the header files in right order I think (tried both).
I tried also with other function (with or without constructor) with same error.
The problem was solved by adding the class files to the project the correct way: Project > Add class. After that the references were linked correctly.
What I did wrong was adding files to the project separately (through: File > Add > File).
Is there something special about how an MFC project handles includes?
Here's the scenario. I like to define my class member functions in the h file, instead of splitting up a class between two files.
In Visual Studio I can create an empty Win32 project and do something like this:
main.cpp:
#include "doubleDef.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
doubleDef.h:
#pragma once
class doubleDef
{
public:
int func();
};
int doubleDef::func()
{
return 4;
}
This builds just fine.
If I take doubleDef.h into an MFC dialog project, and add #include "doubleDef.h" to the h file of the main dialog, I get LNK2005, saying that func is already defined, making it seem as if the #pragma once is being ignored.
If I instead include doubleDef.h in the main dialog's cpp file, everything is fine. But in the empty Win32 I can include doubleDef.h "multiple times" by doing this:
Header.h
#pragma once
#include "doubleDef.h"
Header1.h
#pragma once
#include "doubleDef.h"
main.cpp:
#include "Header.h"
#include "Header1.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
That is, it appears #pragma once works as expected (prevents multiple definitions of doubleDef::func()).
If I turn doubleDef into a template class, then the function definition must be in the h file. Likewise, I can make func inline, either by adding the keyword or implicitly by defining it next to the declaration in the class (as in int func() {return 4;}), and then, again the definition must be in the h file.
According to the documentation, the compiler treats inline as more or less optional, so it seems like if I just want to keep everything in the h file, I can just make everything inline.
What gives?
The #pragma once means the file will only be included once per source file. If you have many source files including it, you will still get a copy in each source file.
By declaring a function inline, you tell the compiler it's OK to have multiple copies - as long as those copies are identical.
The usual way of working is to have the declarations in the header file, and the definitions (implementation) in another source file.
P.S. MFC has nothing to do with your problems.
In your simple Win32 project you have one main file that keeps including the same item, basically a no-op. To have multiple of the same include in referenced in the same file does not create a new link.
However with your MFC project you put your header file into mainfrm.h. That file is included in several other files in that project not just the mainfrm.cpp. Essentially creating a new link for each of those other files the main header was included in.
1>MainFrm.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>FileView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>ClassView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>OutputWnd.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>PropertiesWnd.obj : error LNK2005: "public: int
__thiscall doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in MfcTest.obj
Take a look at that output. You can see each of the other components that thinks it has that object.
To put it another way your original statement of why does it work for one way and not the other is because the complexity of the second example (MFC) actually includes that header all over the place. If you only want it used by the main form then include it in the cpp for it.
This was already answered before, here is more detailed explanation:
You cannot define a function more than once, unless it is inline
You cannot declare a function more than once in the same file.
You do need to declare functions and classes multiple times if they are referenced in multiple .cpp files.
#pragma once prevents multiple declarations in the same file. It will not prevent multiple declarations in different files. Multiple declarations is exactly what you want and it is why you are including the files in multiple .cpp files in the first place.
class N1 {
public:
//Declaration
//Multiple .cpp files need to know about this class and its members
int foo();
};
//Definition
//should be done once. This should go to .cpp file
int N1::foo() {
return 1;
}
In the above example, compile will work fine in multiple .cpp file. The compile routine does not notice multiple definitions. But the linker notices multiple definitions and complains. You have to move the definition to .cpp file or use inline functions.
class N2
{
public:
int foo();
};
inline int N2::foo()
{ //valid, even if it is repeated in different files
return 1;
}
class N3
{
public:
int foo() //always valid
{
return 1;
}
};
i have a full static class, using a std::map
thats the simplified case
.h
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <map>
class Keyboad {
static std::map<char, bool> pressed;
static void keyPressedEvent(char _key);
};
#endif
.cpp
#include "Keyboard.h"
void Keyboard :: keyPressedEvent(char _key) {
Keyboard :: pressed[_key] = true;
}
but there is a problem with the static member variable, because i get
Undefined symbols:
"Keyboard::pressed", referenced from:
__ZN15Keyboard7pressedE$non_lazy_ptr in Keyboard.o
(maybe you meant: __ZN15Keyboard7pressedE$non_lazy_ptr)
ld: symbol(s) not found
collect2: ld returned 1 exit status
when i remove it, it runs ok
why do i get this problem, there should be no problem when using a static variable :/
thanks
You need to define the pressed map in your .cpp file:
#include "Keyboard.h"
std::map<char, bool> Keyboard::pressed;
// The rest as before
You should add this to .cpp file
std::map<char, bool> Keyboad::pressed;
Consider static class members as global variables. Compiler should allocate memory for them inside of the only object file. So you should define them in corresponding source file.
A static member in the class definition is just a declaration. You
still have to provide the definition, exactly like you did for the
function. Just add
std::map<char, bool> Keyboard::pressed;
in a source file somewhere. (For mapping chars, you might also
consider a simple
bool Keyboard::pressed[256];
, indexed with the char converted to unsigned char.)
Consider a simpler case. A global variable counter is declared in multiple header files:
int counter; // This appears in 3 HEADER files.
Few source files do refer it. When you compile and link it, compiler would emit linker error saying that counter is already defined in some set of .OBJ files (Error message is dependent on compiler).
To solve this, you just put extern in front of variable (in all header files):
extern int counter; // This appears in 3 HEADER files.
And when you rebuild it, linker will complain that counter is not defined anywhere.
To solve this issue, you define this variable in one source file (any one):
int counter;
And it resolves the issue.
The static-variable of class is nothing but a global variable, which can be accessed by classname::variablename format. The accessibility is same - global.