I'm getting linkage errors of the following type:
Festival.obj : error LNK2019:
unresolved external symbol "public:
void __thiscall Tree::add(class Price &)"
(?add#?$Tree#VPrice####QAEXAAVPrice###Z)
referenced in function
__catch$?AddBand#Festival##QAE?AW4StatusType##HHH#Z$0
I used to think it has to do with try-catch mechanism, but since been told otherwise. This is an updated version of the question.
I'm using Visual Studio 2008, but I have similar problems in g++.
The relevant code:
In Festival.cpp
#include "Tree.h"
#include <exception>
using namespace std;
class Band{
public:
Band(int bandID, int price, int votes=0): bandID(bandID), price(price), votes(votes){};
...
private:
...
};
class Festival{
public:
Festival(int budget): budget(budget), minPrice(0), maxNeededBudget(0), priceOffset(0), bandCounter(0){};
~Festival();
StatusType AddBand(int bandID, int price, int votes=0);
...
private:
Tree<Band> bandTree;
...
};
StatusType Festival::AddBand(int bandID, int price, int votes){
if ((price<0)||(bandID<0)){
return INVALID_INPUT;
}
Band* newBand=NULL;
try{
newBand=new Band(bandID,price-priceOffset,votes);
}
catch(bad_alloc&){return ALLOCATION_ERROR;}
if (bandTree.find(*newBand)!=NULL){
delete newBand;
return FAILURE;
}
bandTree.add(*newBand);
....
}
In Tree.h:
template<class T>
class Tree{
public:
Tree(T* initialData=NULL, Tree<T>* initialFather=NULL);
void add(T& newData);
....
private:
....
};
Interestingly enough I do not have linkage errors when I try to use Tree functions when type T is a primitive type like an int.
Is there Tree.cpp? If there is, maybe you forgot to link it? Where is the implementation of Tree::add?
In addition I don't see where you call Tree::add. I guess it should be inside the try statement, right after the new?
Just a reminder:
For most compilers (i.e. those that practice separate compilation) the implementation of the member functions of a template class has to be visible during the compilation of the source file that uses the template class. Usually people follow this rule by putting the implementation of the member functions inside the header file.
Maybe Tree::add isn't inside the header? Then a possible solution in the discussed case will be to put Tree::add implementation inside the header file.
The difference between regular classes and template classes exists because template classes are not "real" classes - it is, well, a template. If you had defined your Tree class as a regular class, the compiler could have used your code right away. In case of a template the compiler first "writes" for you the real class, substituting the template parameters with the types you supplied. Now, compiler compiles cpp files one by one. He is not aware of other cpp files and can use nothing from other cpp files. Let's say your implementation of Tree:add looks like this:
void Tree::add(T& newData)
{
newData.destroyEverything();
}
It is totally legitimate as long as your T has method destroyEverything. When the compiler compiles Class.cpp it wants to be sure that you don't do with T anything it doesn't know. For example Tree<int> won't work because int doesn't have destroyEverything. The compiler will try to write your code with int instead of T and find out that the code doesn't compile. But since the compiler "sees" only the current cpp and everything it includes, it won't be able to validate add function, since it is in a separate cpp.
There won't be any problem with
void Tree::add(int& newData)
{
newData.destroyEverything();
}
implemented in a separate cpp because the compiler knows that int is the only acceptable type and can "count on himself" that when he gets to compile Tree.cpp he will find the error.
Are you sure the try/catch has anything to do with it? What happens if you simply comment out the try and catch lines, leave the rest of the code as it is, and build that?
It might just be that you're missing the library that defines Tree::add(class Price &) from your link line.
Update: using Tree functions with a primitive type doesn't result in a linking error.
I updated my question in light of some of the things that were said.
As others have stated you need to show the implementation of Treee::add() and tell us how you are linking it.
On an unrelated point, if you are using constructs like:
Band* newBand=NULL;
try{
newBand=new Band(bandID,price-priceOffset,votes);
}
catch(bad_alloc&){return ALLOCATION_ERROR;}
throughout your code, you are frankly wasting your time. The chances of you getting to a point of memory exhaustion in a modern OS are remote and the chances of you doing anything useful after it has happened are roughly zero. You will be much better off simply saying:
Band * newBand = new Band ( bandID, price - priceOffset, votes );
ot possibly:
Band newBand( bandID, price - priceOffset, votes );
and forgetting the exception handling in this case.
You wrote in a comment:
I considered this but the function is part of Tree.h, and I do include it. The function defined is: template void Tree::add(T& newData); We call it the following way: priceTree.add(*newPriceNode); whereas priceTree is Tree, both of which are defined in the cpp file in question.
instead of:
priceTree.add(*newPriceNode);
try:
priceTree.add(newPriceNode); //no "*" before "newPriceNode"
add() takes a reference to a node, not a pointer to a node (according to your definition of Tree).
You're getting linkage errors, not compiler errors. This tells us that the compiler knew what sort of function Tree::add() is, but didn't have a definition. In Tree.h, I see a declaration of the add() function, but not a definition. It looks odd to me; does anybody know where Tree.h came from?
Usually a template class comes with member function definitions in the include file, since the functions have to be instantiated somewhere, and the simplest thing is for the compiler to instantiate when used and let the linker sort it out. If the definitions are in Tree.h, I'd expect everything to work as planned.
So, I'm going to go out on a limb and suggest that the definitions are in a separate file, not linked in, and that there are provisions elsewhere for instantiating for basic types like Tree<int>. This is presumably to streamline compilation, as normally these things are compiled in multiple places, and that takes time.
What you need to do in that case is to find where Tree<int> is instantiated, and add an instantiation for your class.
I could be way off base here, but my explanation does fit the facts you've given.
Edit after first comments:
Templates are somewhat trickier than ordinary functions, which usually isn't a real problem. If the definitions for all the calls were in Tree.h, then Festival.cpp would be able to instantiate Tree<Band> and everything would be cool. That's the usual technique, and you're running into this problem because you're not using it.
When you write a function, it gets compiled, and the linker will find it. Any routine calling that function needs to know the function prototype, so it will know how to call it. When you write a template, you're not writing anything that will go directly into the program, but any use of the template counts as writing all the functions.
Therefore, there has to be some use of Tree<Band> somewhere in your program, for there to be a Tree<Band>::add() function compiled. The definition of Tree<T>::add has to be available to the compiler when Tree<Band> is instantiated, because otherwise the compiler has no idea what to compile. In this case, it's generating the function call, confident that you'll make sure the function is compiled elsewhere.
Therefore, you have to instantiate Tree<Band> inside a file that has access to both the definitions for Tree<T> and Band. This probably means a file that is, or includes, Tree.cpp and includes Festival.h.
The linker is already using Tree.cpp, but Tree.cpp doesn't have Tree<Band> defined in it, so it's meaningless to the linker. Templates are only useful for the compiler, and the linker only operates on what the compiler generated from templates.
The quick way to solve this is to take the definitions from Tree.cpp and put them in Tree.h. That will be likely to increase compilation and link times, unfortunately. The other technique is to instantiate all template uses in Tree.cpp, so that they'll be compiled there.
Related
Okay so I recently learned how the compiler exactly works and what the "linker" is. From the tutorial videos I've watched I clearly saw that if I include more than once a declaration, to say:
void Log(const char* message);
I would get an error since I am declaring it more than once. But currently, as I am testing it, I've created a header file which contains that particular declaration and I've included it a couple of times in my Main compilation unit, as so:
#include "Log.h"
#include "Log.h"
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems. Since the videos are 2-3 years old, I thought maybe there has been an update, which alltogether removes the need of guards and pragmas, but I do not know for sure.
The tutorials you've seen are correct. You cannot have more than one definition of something unless you use special techniques.
In this case though you don't have a definition.
void Log(const char* message);
is a declaration and you are allowed to have multiples of those. If you change the code to
void Log(const char* message) {}
then you would have a function definition and will get an error.
I would get an error since I am declaring it more than once.
Re-declaration is generally allowed, as long as you don't mix different kinds of declarations with the same name. Following is perfectly legal C++, and always has been:
void Log(const char* message);
void Log(const char* message);
You may have been confused with the one definition rule, which disallows defining things more than once.
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems.
If your header doesn't define anything, then it doesn't need a header guard. It's however simpler to just conventionally always keep the guard so that there is no need to keep track of whether there are definitions or not.
Bonus answer: All definitions are also declarations. It is usually easy to distinguish definitions of classes and functions from forward declarations:
return_type function_name(argument_list); // not a definition of function
return_type function_name(argument_list) { ... } // is a definition of function
class class_name; // not a definition of class
class class_name { // is a definition of class
void member_function(); // not a definition of function
void inline_member_function() { ... }; // is a definition of function
};
void class_name::member_function() { ... } // is a definition of function
Distinguishing variable definitions is a bit harder. Always check the rules when unsure.
this a function forward declaration and you just let the compiler know that a function X will be defined later. in some resources you will find out it's written/said that multiple declaration isn't allowed, but i think cuz of the clean code approach, not a compiler issue. and your case, you just include the declaration twice, the same if you declared the function in two different header files and included both of them in a source file.
Cherno's tutorials?
I think its made crystal clear in the videos that you can't have multiple definitions of a function. The custom header files that you've created are basically chunks of code copy-pasted hence if they include different definitions of the same function or say class it will result in ambiguity and throw an error as expected.
Edit: The point that he wanted to make -
If you write those two same function definitions together in a file then obviously it will throw up an error due to ambiguity arising as I mentioned above, which is detected by the compiler, since its only in a single file.
But when you place those two same definitions in a different file, say your custom created header "log.h" then when you import them into your cpp file twice (or say you import them in another cpp file and build the solution like in visual studio) it will throw up a linker error as the linker is involved (multiple files - wherein the job of the linker is to link them into a combined executable) and it cannot select multiple definitions present in different files. Hence for this case you will get the multiple definitions/signature error. (And including pragmas suppress warnings)
A Solution to resolve that is making the functions static, so that they are defined internally or only for the file they are being compiled against. This makes it possible to have multiple function definitions of the same function in different files with no linking error. Another option is to make it in-line. These cases provide you with multiple definitions with no errors, otherwise it will throw up errors.
At this link, the following was mentioned:
add.cpp:
int add(int x, int y)
{
return x + y;
}
main.cpp:
#include <iostream>
int add(int x, int y); // forward declaration using function prototype
int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}
We used a forward declaration so that the compiler would know what "add" was when compiling main.cpp. As previously mentioned, writing forward declarations for every function you want to use that lives in another file can get tedious quickly.
Can you explain "forward declaration" further? What is the problem if we use it in the main function?
Why forward-declare is necessary in C++
The compiler wants to ensure you haven't made spelling mistakes or passed the wrong number of arguments to the function. So, it insists that it first sees a declaration of 'add' (or any other types, classes, or functions) before it is used.
This really just allows the compiler to do a better job of validating the code and allows it to tidy up loose ends so it can produce a neat-looking object file. If you didn't have to forward declare things, the compiler would produce an object file that would have to contain information about all the possible guesses as to what the function add might be. And the linker would have to contain very clever logic to try and work out which add you actually intended to call, when the add function may live in a different object file the linker is joining with the one that uses add to produce a dll or exe. It's possible that the linker may get the wrong add. Say you wanted to use int add(int a, float b), but accidentally forgot to write it, but the linker found an already existing int add(int a, int b) and thought that was the right one and used that instead. Your code would compile, but wouldn't be doing what you expected.
So, just to keep things explicit and avoid guessing, etc, the compiler insists you declare everything before it is used.
Difference between declaration and definition
As an aside, it's important to know the difference between a declaration and a definition. A declaration just gives enough code to show what something looks like, so for a function, this is the return type, calling convention, method name, arguments, and their types. However, the code for the method isn't required. For a definition, you need the declaration and then also the code for the function too.
How forward-declarations can significantly reduce build times
You can get the declaration of a function into your current .cpp or .h file by #includ'ing the header that already contains a declaration of the function. However, this can slow down your compile, especially if you #include a header into a .h instead of .cpp of your program, as everything that #includes the .h you're writing would end up #include'ing all the headers you wrote #includes for too. Suddenly, the compiler has #included pages and pages of code that it needs to compile even when you only wanted to use one or two functions. To avoid this, you can use a forward-declaration and just type the declaration of the function yourself at the top of the file. If you're only using a few functions, this can really make your compiles quicker compared to always #including the header. For really large projects, the difference could be an hour or more of compile time bought down to a few minutes.
Break cyclic references where two definitions both use each other
Additionally, forward-declarations can help you break cycles. This is where two functions both try to use each other. When this happens (and it is a perfectly valid thing to do), you may #include one header file, but that header file tries to #include the header file you're currently writing... which then #includes the other header, which #includes the one you're writing. You're stuck in a chicken and egg situation with each header file trying to re #include the other. To solve this, you can forward-declare the parts you need in one of the files and leave the #include out of that file.
Eg:
File Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
File Wheel.h
Hmm... the declaration of Car is required here as Wheel has a pointer to a Car, but Car.h can't be included here as it would result in a compiler error. If Car.h was included, that would then try to include Wheel.h which would include Car.h which would include Wheel.h and this would go on forever, so instead the compiler raises an error. The solution is to forward declare Car instead:
class Car; // forward declaration
class Wheel
{
Car* car;
};
If class Wheel had methods which need to call methods of Car, those methods could be defined in Wheel.cpp and Wheel.cpp is now able to include Car.h without causing a cycle.
The compiler looks for each symbol being used in the current translation unit is previously declared or not in the current unit. It is just a matter of style providing all method signatures at the beginning of a source file while definitions are provided later. The significant use of it is when you use a pointer to a class as member variable of another class.
//foo.h
class bar; // This is useful
class foo
{
bar* obj; // Pointer or even a reference.
};
// foo.cpp
#include "bar.h"
#include "foo.h"
So, use forward-declarations in classes when ever possible. If your program just has functions( with ho header files), then providing prototypes at the beginning is just a matter of style. This would be anyhow the case had if the header file was present in a normal program with header that has only functions.
Because C++ is parsed from the top down, the compiler needs to know about things before they are used. So, when you reference:
int add( int x, int y )
in the main function the compiler needs to know it exists. To prove this try moving it to below the main function and you'll get a compiler error.
So a 'Forward Declaration' is just what it says on the tin. It's declaring something in advance of its use.
Generally you would include forward declarations in a header file and then include that header file in the same way that iostream is included.
The term "forward declaration" in C++ is mostly only used for class declarations. See (the end of) this answer for why a "forward declaration" of a class really is just a simple class declaration with a fancy name.
In other words, the "forward" just adds ballast to the term, as any declaration can be seen as being forward in so far as it declares some identifier before it is used.
(As to what is a declaration as opposed to a definition, again see What is the difference between a definition and a declaration?)
When the compiler sees add(3, 4) it needs to know what that means. With the forward declaration you basically tell the compiler that add is a function that takes two ints and returns an int. This is important information for the compiler becaus it needs to put 4 and 5 in the correct representation onto the stack and needs to know what type the thing returned by add is.
At that time, the compiler is not worried about the actual implementation of add, ie where it is (or if there is even one) and if it compiles. That comes into view later, after compiling the source files when the linker is invoked.
one quick addendum regarding: usually you put those forward references into a header file belonging to the .c(pp) file where the function/variable etc. is implemented. in your example it would look like this:
add.h:
extern int add(int a, int b);
the keyword extern states that the function is actually declared in an external file (could also be a library etc.).
your main.c would look like this:
#include
#include "add.h"
int main()
{
.
.
.
int add(int x, int y); // forward declaration using function prototype
Can you explain "forward declaration"
more further? What is the problem if
we use it in the main() function?
It's same as #include"add.h". If you know,preprocessor expands the file which you mention in #include, in the .cpp file where you write the #include directive. That means, if you write #include"add.h", you get the same thing, it is as if you doing "forward declaration".
I'm assuming that add.h has this line:
int add(int x, int y);
One problem is, that the compiler does not know, which kind of value is delivered by your function; is assumes, that the function returns an int in this case, but this can be as correct as it can be wrong. Another problem is, that the compiler does not know, which kind of arguments your function expects, and cannot warn you, if you are passing values of the wrong kind. There are special "promotion" rules, which apply when passing, say floating point values to an undeclared function (the compiler has to widen them to type double), which is often not, what the function actually expects, leading to hard to find bugs at run-time.
At this link, the following was mentioned:
add.cpp:
int add(int x, int y)
{
return x + y;
}
main.cpp:
#include <iostream>
int add(int x, int y); // forward declaration using function prototype
int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}
We used a forward declaration so that the compiler would know what "add" was when compiling main.cpp. As previously mentioned, writing forward declarations for every function you want to use that lives in another file can get tedious quickly.
Can you explain "forward declaration" further? What is the problem if we use it in the main function?
Why forward-declare is necessary in C++
The compiler wants to ensure you haven't made spelling mistakes or passed the wrong number of arguments to the function. So, it insists that it first sees a declaration of 'add' (or any other types, classes, or functions) before it is used.
This really just allows the compiler to do a better job of validating the code and allows it to tidy up loose ends so it can produce a neat-looking object file. If you didn't have to forward declare things, the compiler would produce an object file that would have to contain information about all the possible guesses as to what the function add might be. And the linker would have to contain very clever logic to try and work out which add you actually intended to call, when the add function may live in a different object file the linker is joining with the one that uses add to produce a dll or exe. It's possible that the linker may get the wrong add. Say you wanted to use int add(int a, float b), but accidentally forgot to write it, but the linker found an already existing int add(int a, int b) and thought that was the right one and used that instead. Your code would compile, but wouldn't be doing what you expected.
So, just to keep things explicit and avoid guessing, etc, the compiler insists you declare everything before it is used.
Difference between declaration and definition
As an aside, it's important to know the difference between a declaration and a definition. A declaration just gives enough code to show what something looks like, so for a function, this is the return type, calling convention, method name, arguments, and their types. However, the code for the method isn't required. For a definition, you need the declaration and then also the code for the function too.
How forward-declarations can significantly reduce build times
You can get the declaration of a function into your current .cpp or .h file by #includ'ing the header that already contains a declaration of the function. However, this can slow down your compile, especially if you #include a header into a .h instead of .cpp of your program, as everything that #includes the .h you're writing would end up #include'ing all the headers you wrote #includes for too. Suddenly, the compiler has #included pages and pages of code that it needs to compile even when you only wanted to use one or two functions. To avoid this, you can use a forward-declaration and just type the declaration of the function yourself at the top of the file. If you're only using a few functions, this can really make your compiles quicker compared to always #including the header. For really large projects, the difference could be an hour or more of compile time bought down to a few minutes.
Break cyclic references where two definitions both use each other
Additionally, forward-declarations can help you break cycles. This is where two functions both try to use each other. When this happens (and it is a perfectly valid thing to do), you may #include one header file, but that header file tries to #include the header file you're currently writing... which then #includes the other header, which #includes the one you're writing. You're stuck in a chicken and egg situation with each header file trying to re #include the other. To solve this, you can forward-declare the parts you need in one of the files and leave the #include out of that file.
Eg:
File Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
File Wheel.h
Hmm... the declaration of Car is required here as Wheel has a pointer to a Car, but Car.h can't be included here as it would result in a compiler error. If Car.h was included, that would then try to include Wheel.h which would include Car.h which would include Wheel.h and this would go on forever, so instead the compiler raises an error. The solution is to forward declare Car instead:
class Car; // forward declaration
class Wheel
{
Car* car;
};
If class Wheel had methods which need to call methods of Car, those methods could be defined in Wheel.cpp and Wheel.cpp is now able to include Car.h without causing a cycle.
The compiler looks for each symbol being used in the current translation unit is previously declared or not in the current unit. It is just a matter of style providing all method signatures at the beginning of a source file while definitions are provided later. The significant use of it is when you use a pointer to a class as member variable of another class.
//foo.h
class bar; // This is useful
class foo
{
bar* obj; // Pointer or even a reference.
};
// foo.cpp
#include "bar.h"
#include "foo.h"
So, use forward-declarations in classes when ever possible. If your program just has functions( with ho header files), then providing prototypes at the beginning is just a matter of style. This would be anyhow the case had if the header file was present in a normal program with header that has only functions.
Because C++ is parsed from the top down, the compiler needs to know about things before they are used. So, when you reference:
int add( int x, int y )
in the main function the compiler needs to know it exists. To prove this try moving it to below the main function and you'll get a compiler error.
So a 'Forward Declaration' is just what it says on the tin. It's declaring something in advance of its use.
Generally you would include forward declarations in a header file and then include that header file in the same way that iostream is included.
The term "forward declaration" in C++ is mostly only used for class declarations. See (the end of) this answer for why a "forward declaration" of a class really is just a simple class declaration with a fancy name.
In other words, the "forward" just adds ballast to the term, as any declaration can be seen as being forward in so far as it declares some identifier before it is used.
(As to what is a declaration as opposed to a definition, again see What is the difference between a definition and a declaration?)
When the compiler sees add(3, 4) it needs to know what that means. With the forward declaration you basically tell the compiler that add is a function that takes two ints and returns an int. This is important information for the compiler becaus it needs to put 4 and 5 in the correct representation onto the stack and needs to know what type the thing returned by add is.
At that time, the compiler is not worried about the actual implementation of add, ie where it is (or if there is even one) and if it compiles. That comes into view later, after compiling the source files when the linker is invoked.
one quick addendum regarding: usually you put those forward references into a header file belonging to the .c(pp) file where the function/variable etc. is implemented. in your example it would look like this:
add.h:
extern int add(int a, int b);
the keyword extern states that the function is actually declared in an external file (could also be a library etc.).
your main.c would look like this:
#include
#include "add.h"
int main()
{
.
.
.
int add(int x, int y); // forward declaration using function prototype
Can you explain "forward declaration"
more further? What is the problem if
we use it in the main() function?
It's same as #include"add.h". If you know,preprocessor expands the file which you mention in #include, in the .cpp file where you write the #include directive. That means, if you write #include"add.h", you get the same thing, it is as if you doing "forward declaration".
I'm assuming that add.h has this line:
int add(int x, int y);
One problem is, that the compiler does not know, which kind of value is delivered by your function; is assumes, that the function returns an int in this case, but this can be as correct as it can be wrong. Another problem is, that the compiler does not know, which kind of arguments your function expects, and cannot warn you, if you are passing values of the wrong kind. There are special "promotion" rules, which apply when passing, say floating point values to an undeclared function (the compiler has to widen them to type double), which is often not, what the function actually expects, leading to hard to find bugs at run-time.
I have read many posts before posting this one, I couldnt find a solution because non of them (those I read) were on data structures.
I have two data structures (If it matter, a Heap and a UF).
Both of them are implemented in the .h file.
I'm getting the "Multiple definition of.." "First defined here" errors only on member functions implemented outside of the class (such as int UnionFind::Find(int i) )
It happens for the c'tors and d'tors also, but when I implement them in the class itself, it disappear.
I really have no clue why it is happening.
I have followed the includes in all of my files and there are no double includes or loops.
I'm also using an AVL tree, and it does not happen there, everything there is implemented in the .h file outside of the class.
These are the errors im getting :
/tmp/ccp8fP73.o: In function `UnionFind::Find(int)':
main.cpp:(.text+0x0): multiple definition of `UnionFind::Find(int)'
/tmp/ccVxSiPy.o:Elections.cpp:(.text+0x0): first defined here
/tmp/ccp8fP73.o: In function `UnionFind::Union(int, int)':
main.cpp:(.text+0x108): multiple definition of `UnionFind::Union(int, int)'
/tmp/ccVxSiPy.o:Elections.cpp:(.text+0x108): first defined here
If you need more info, please tell me.
Thank you
If I understand you correctly, you are doing things like this:
// C.h
class C
{
void f(); // declaration of f; ok to include in many modules
};
// definition of f; must not exist in more than one module
void C::f()
{
}
That doesn't work because the definition of f() will wind up in every module that includes C.h, leading to exactly the linker error you describe. You can fix this by either marking f() as inline, or by moving the definition of f() to a separate cpp file.
There is one special case where this is allowed, and that's when f() is a template (either directly or because C is a template). In that case, the definition must be in the header so the compiler can know how to instantiate it for whatever type(s) you specify. This does make life difficult for the linker since you can and often do end up with the sorts of redundant definitions that would normally be errors (e.g if you use f<int>() in more than one module). Special behavior is needed to handle this.
Incidentally, the reason things work when you move the function bodies inside the class definition is because that has the effect of making them implicitly inline.
If you want to create your templates manually..
//1. include the template code..
#include <template/list.tmpl.c>
// 2. instantiate the instances that use it..
#include "/c/viewer/src/ViewObject.h"
#include "/c/viewer/src/WindowAdaptor.h"
template class List<ViewObject>;
template class List<WindowAdaptor>;
I am not sure how this code is working. As per my understanding all declared method should be defined.
class Test
{
public:
void foo();
};
int main()
{
Test t;
return 0;
}
In class Test, method foo() is declared but not defined, still this code works fine. Please explain why this is working. Isn't it wrong to do this because only declared method is of no use unless it is in abstract class or interface ? My guess is declaration of method tells compiler about it so compiler doesn't complain about it and it will work fine until someone will actually try to use this method. If this is so, still it make no sense why this is allowed ? Is there any specific reason or use of this ?
Compiler does not complain about such a code because it can't - you could have written function definition in some other file. Only linker can tell you that there is no function definition in all of your files. But because you didn't used that function at all, there is no reference to this function, linker does not complain too.
It "works" because nothing ever calls the function Test::foo.
The compiler has no possible way to know if Test is meant to be defined in the current compile unit [1], or there is a test.cpp that implements the function Test::foo. Consequently, the compiler has to accept that you don't define the function here.
In the case where you do have two files, one withmain and one containing Test::foo, this gets combined at the later, linking stage, of the compilation, when the compiler takes all the different components your software consists of and puts them together. This may be "in the future" in your learning process, but this is the reason the compiler doesn't complain about it "now". And since you don't actually try to use the function Test::foo, there is "no need" for it to actually exist, so no error is produced.
[1] Note that it doesn't really matter to the actual compiler if you have class Test in the main file, or it was included from test.h, since the #include part is dealt with before the compiler actually tries to "understand" the code.
Edit: One might of course argue here that this code is nonsense. What is the point of declaring a function that isn't used. But that is not really for the compiler/linker to decide. If you don't use something, you don't need to define it. Those are the rules.