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;
}
};
Related
I have a Visual C++ solution with 2 projects: rectangle and project3.
In rectangle project I have rect.cpp and rect.h.
rect.h
#ifndef rect_h
#define rect_h
class Rect
{
public:
Rect();
int m_h;
int m_w;
};
#endif //rect_h
rect.cpp
#include "rect.h"
Rect::Rect()
{
m_h = 1;
m_w = 5;
}
whenever I try to create rect object from the rectangle project it succeeds.
But when I try to do the same from the project3 it produces a linker error.
LNK2019: unresolved external symbol "public: __thiscall
Rect::Rect(void)" (??0Rect##QAE#XZ) referenced in function _main
1>C:\Users\mbaro\documents\visual studio
2017\Projects\Project2\Debug\Project3.exe : fatal error LNK1120: 1
unresolved externals
main.cpp (in project 3)
#include "rect.h"
using namespace std;
int main()
{
Rect* a = new Rect();
return 0;
}
I kind of feel that class definition is picked up successfully, but the linker can not link the constructor code from rect.cpp.
What is the problem and how to solve it?
Thanks.
The error is normal: you told the compiler where it could find the .h files, but you did not tell the linker where it could find the .obj files.
It may depend on the exact VS version, but in Project/Properties, you should find Linker/Input and there Additional dependencies. If you only need one or two object files (xxx.obj) from the other project, add them here. That way, you avoid code duplication, which will be a nightmare for future maintenance...
If you have many common files, you should considere to put them in an auxilliary project that would build a (static)library in the same solution, and then link the library in both project (and of course give access to header files of the library project for the other projects using the library).
I have already started writing a long, long answer. Then i realized, what You may be missing is that despite Your class is named "Person" the header file You should have added is named "rect.h".
Also Your constructor cannot have a declaration of values in the header file (EDIT:not true, I was mistaken). In the header file, try using:
Person(int h, int w);
You declare what will be needed, not what You already have. If You want those to be specifically what You wrote the constructor should be:
Person();
in .h
and
Person::Person()
{
m_h = 1;
m_w = 5;
}
in .cpp.
If You need more detailed description of using include, I have already written a big part of it, so don't hesitate to ask.
I have a question concerning inlining methods.
I am using a library developed for collision models. One header file responsible for graphic interface contains declaration and implementation of the functions but the functions are not inlined. Therefore, it is impossible to include those functions in several translation units.
As an illustration here is a dummy code I designed for illustration :
LivingBeing.h
#ifndef LIVINGBEING_H
#define LIVINGBEING_H
class LivingBeing
{
public:
LivingBeing(double _size);
void breathe();
private:
double size;
};
//////////////
LivingBeing::LivingBeing(double _size)
{
size = _size;
}
void LivingBeing::breathe()
{
// do something
}
#endif
Forest.h
#ifndef FOREST_H
#define FOREST_H
#include "LivingBeing.h"
class Forest
{
public:
Forest(int _numberLivingBeings);
private:
int numberLivingBeings;
};
#endif
Forest.cpp
#include "Forest.h"
Forest::Forest(int _numberLivingBeings)
{
numberLivingBeings = _numberLivingBeings;
// Call LivingBeing constructor, methods etc...
}
Main.cpp
#include "Forest.h"
int main()
{
Forest forest = Forest(10);
return 0;
}
This code does not compile unless I add the inline keyword in front of the constructor LivingBeing and the method breathe. The error message is :
1>main_test.obj : error LNK2005: "public: __thiscall LivingBeing::LivingBeing(double)" (??0LivingBeing##QAE#N#Z) already defined in Forest.obj
1>main_test.obj : error LNK2005: "public: void __thiscall LivingBeing::breathe(void)" (?breathe#LivingBeing##QAEXXZ) already defined in Forest.obj
1>C:\Users\******\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\Test_3.exe : fatal error LNK1169: one or more multiply defined symbols found
My question is : what is the drawbacks of inlining methods ? The real library I am using is pretty large, I would like to inline methods from a specific file (in my example it would be LivingBeing.h) so that it is possible to use those methods in several .cpp files. What am I risking by changing the source file as such ?
Thanks a lot
You are defining functions (LivingBeing::LivingBeing and LivingBeing::breathe) in a header, which means there will be a definition in each translation unit that includes that header. This breaks the One Definition Rule (ODR), hence the link error.
You have three options:
Move the function definitions into a source file so they are only defined once; or
Declare them inline to allow multiple identical definitions; or
Move the definitions inside the class definition, which implicitly makes them inline.
what is the drawbacks of inlining methods ?
Possibly increased compilation time and executable size; but you'd need to measure to see whether there's any noticable difference.
A less stable API - client code will need recompiling whenever any inline function changes.
The possibility of accidentally breaking the ODR, for example if a function contains macros which might have different expansions in different translation units.
Just because a method is defined in a "source" file (.c/.cpp) doesn't mean it won't be inlined... link-time operations may perform that optimization. Oppositely, just because a method is declared and implemented as inline in a header file doesn't mean it will be inlined. In general, I define methods in a header file if they are very simple, e.g. int getWidth() const { return width; }, or MyObj* getNext() { return internal_itor ? internal_itor->next : 0; }
I've spent the last 2 days searching for and implementing the answers from similar questions into my code with little success. I have an API that is an external .dll (windows) and I have the header file included into my .cpp file to reference the API.
However I have this issue that no matter what I do, I always get an unresolved external symbol that references this line in my .h file. Yes, I have used Google and modified the answers I found into my code, with no success.
Foo.h
Class Foo {
public:
static Foo* Interface_Get(char* dllfilename);
Foo.cpp
// I declare this just underneath the #include "Foo.h" header
Foo *foo = 0;
Inside my main function I declare it as this (along with some other functions that are fine).
//This has already been created and both Header and .dll are in the same directory.
Foo::Interface_Get("bar.dll");
And I get this error
error LNK2019: unresolved external symbol
"public: static class Foo * __cdecl Foo::Interface_Get(char *)"
I've tried everything I know (This is my first .dll creation experience) I have a feeling I am missing something painfully obvious, but for the life of me I cannot see it.
Entire Foo.cpp
#include "Foo.h"
Foo* Foo::Interface_Get(char* dllfilename); //May not be redeclared outside class error
Foo* foo = 0;
bool Frame()
{
if (foo->Key_Down(DIK_ESCAPE))
return false;
return true;
}
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
foo->Interface_Get("bar.dll");
foo->System_SetState(grSTATE_FRAME, Frame);
foo->System_SetState(grSTATE_WINDOWED, true);
foo->System_SetState(grSTATE_KEYBOARD, true);
foo->System_Initiate();
foo->System_Start();
foo->System_Shutdown();
foo->Inferface_Release();
return 0;
}
This question explains common problems, and in your case it's (probably) a combination of:
(possibly) forgetting to implement the function
forgetting __declspec(dllexport)
forgetting to link against the library
You need to provide function definition for Interface_Get(char* dllfilename); if you haven't done that.
This only redeclares function again, you need to provide function like below format with {}
Foo* Foo::Interface_Get(char* dllfilename); //May not be redeclared outside class error
Foo.cpp
Foo* Foo::Interface_Get(char* dllfilename)
{
//....
return new Foo();
}
I am now building a C++ DLL library. Today I have met a confusing problem: in this library I can define class but not functions. To be more specific, I give the following codes to illustrate my problem:
namespace fundamental
{
class Tree
{
public:
Tree() {};
~Tree() {};
int x;
};
/*int anyfunction()
{
return 1;
}*/
}
The above definition is in the header file, and this file will be invoked by other files. My problem is that if I commented the function part (int anyfunction()) everything was fine, but if I added this function, I would get the following errors:
page_analysis.obj : error LNK2005: "int __cdecl fundamental::anyfunction(void)" (?anyfunction#fundamental##YAHXZ) already defined in geo_box.obj
1>pa_region_properties.obj : error LNK2005: "int __cdecl fundamental::anyfunction(void)" (?anyfunction#fundamental##YAHXZ) already defined in geo_box.obj
My question is why I will get LNK2005 error only for functions but not for classes. Any ideas?
If you define something in a header file, then that definition will be duplicated in any translation unit (roughly speaking, every source file) that includes that header. Sometimes, multiple definitions are an error.
Classes can be defined in multiple translation units, as long as the definitions are identical; indeed, they must be defined in any translation unit that uses them.
Functions usually can't, but you can allow it by declaring it inline:
inline int anyfunction() {return 1;}
or you could move the definition to a single source file, and only declare it in the header:
// header
namespace fundamental {
int anyfunction();
}
// source file
int fundamental::anyfunction() {return 1;}
Most likely you have included that function via a header into different translation units (aka cpp-file). If you really need that function to be inlined, use "inline":
inline int anyfunction()
{
return 1;
}
HTH Torsten
I have a problem with generics in c++.I have two Matrix.h and Matrix.cpp files.Here is files:
#pragma once
template<class T>
class Matrix
{
public:
static T** addSub(int size,T** firstMatrix,T** secondMatrix,int operation);
}
and Matrix.cpp
#include "Martix.h"
template<class T>
static T** Matrix<T>::addSub( int n,T **firstMatrix,T **secondMatrix,int operation)
{
//variable for saving result operation
T **result = new T*[n];
//create result matrix
for( int i=0;i<n;i++)
result[i] = new T[n];
//calculate result
for( int i=0;i<n;i++)
for(int j=0;j<n;j++)
result[i][j] =
(operation == 1) ? firstMatrix[i][j] + secondMatrix[i][j]:
firstMatrix[i][j] - secondMatrix[i][j];
return result;
}
when I run these I get the below error:
Error 1 error LNK2019: unresolved external symbol "public: static int * * __cdecl Matrix<int>::addSub(int,int * *,int * *,int)" (?addSub#?$Matrix#H##SAPAPAHHPAPAH0H#Z) referenced in function "public: static int * * __cdecl Matrix<int>::strassenMultiply(int,int * *,int * *)" (?strassenMultiply#?$Matrix#H##SAPAPAHHPAPAH0#Z) C:\Users\ba.mehrabi\Desktop\Matrix\matrixMultiplication\main.obj matrixMultiplication
what is the problem?
Unfortunately, you can't have the declaration of a template class in the *.cpp files. The full definition has to stay in the header file. This is a rule of many C++ compilers.
See this: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
A template is not a class or a function. A template is a "pattern"
that the compiler uses to generate a family of classes or functions.
In order for the compiler to generate the code, it must see both
the template definition (not just declaration) and the specific
types/whatever used to "fill in" the template. For example, if you're
trying to use a Foo, the compiler must see both the Foo template
and the fact that you're trying to make a specific Foo.
Your compiler probably doesn't remember the details of one .cpp
file while it is compiling another .cpp file. It could, but most do
not and if you are reading this FAQ, it almost definitely does not.
BTW this is called the "separate compilation model."
The link has a workaround, but keep in mind that a template is a glorified macro so the header file is probably the best place for it.
The poster of this SO post shows a demonstration of the workaround.
First of all, the definition of functions of a class template, should go in the header itself.
Second, if you define the static member function out of class (though in the header itself), then don't use the static keyword (in the definition). It only needed in the declaration only.
Add
template Matrix<int>;
at the end of your cpp file and it will work. But you need to learn a few things about templates, otherwise you'll have to deal with lots of issues you don't understand.