2

I am new to C++. I had an unresolved external symbol error while using vectors and didn't know what was going wrong so I've replicated it here.

I am using MS Visual Studio 2011. The exact error is:

error LNK2001: unresolved external symbol "class std::vector > abc" (?abc@@3V?$vector@VmyClass@@V?$allocator@VmyClass@@@std@@@std@@A)

I have my class declaration in myClass.h:

#ifndef __MYCLASS__
#define __MYCLASS__

class myClass{
    public:
        int var;
        myClass(void);
        myClass (int k);
};
#endif  

and my class definition in myClass.cpp:

#include"myClass.h"

myClass::myClass(void){
        var=0;
    }
myClass::myClass (int k){
        var=k;
    }

header.h :

ifndef __HEADER__
#define __HEADER__

    #include<iostream>
    #include<vector>
    #include"myClass.h"
    using namespace std;

    extern std::vector<myClass> abc;

#endif

main.cpp :

#include <iostream>
#include <vector>
#include "myClass.h"
#include "header.h"

using namespace std;

int main(){
    abc.push_back(myClass(5));

    return 1;
}

This is where I get the unresolved external symbol error. Now I tried putting all of these in a single file and it compiled alright.

THE FOLLOWING FILE IS NOT INCLUDED IN THE ABOVE PROJECT.

#include<iostream>
#include<vector>
#include"myClass.h"
using namespace std;

    class myClass{
    public:
        int var;
        myClass(void){
        var=0;
    }
    myClass (int k){
        var=k;
    }
};


int main(){
    std::vector<myClass> abc;
    abc.push_back(myClass(5));

    return 1;
}

The solution has been given at What is an undefined reference/unresolved external symbol error and how do I fix it? but I can't figure out how to implement it.

Community
  • 1
  • 1
Tanmay
  • 366
  • 1
  • 4
  • 22

3 Answers3

3

You do not have a definition for this vector:

extern std::vector<myClass> abc;

An extern declaration only tells the compiler that the object exists and it is defined somewhere. But you haven't defined it anywhere.

Add this at global namespace scope in one (and only one!) of your .cpp files:

std::vector<myClass> abc;

Actually, considering that you are not using abc from different translation units (i.e. .cpp files) you do not need the extern declaration at all. Just place your vector in main.cpp, since that is the only place where you are using it.

Also, avoid using directives, especially at namespace scope (since it easily leads to nasty name clashes with entities from the Standard Library):

using namespace std; // THIS IS BAD, DON'T DO IT

Considering that you are qualifying the names of entities from the std namespace already, you don't really need the above.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • `votes++` for the using namespace part. I wish when advised people would provide a good explanation to *why*. The internet and tons of books use it so it may not make sense or appear untrue. OP uses it in a header which is a special case of bad! – ChiefTwoPencils Jun 14 '13 at 18:26
  • Can you please explain the part about namespaces or link to an explanation? Thanks! – idoby Jun 14 '13 at 18:29
  • @IBY: I edited the answer to hint at the reason: if you import entities from the `std` namespace into the global namespace, then you may have bad name clashes. If you had any variable or function or class of yours named `count`, `find`, `map`, `distance` etc., those names could suddenly mean `std::count`, `std::find`, `std::map`, `std::distance`, ... (depending on the context of course) – Andy Prowl Jun 14 '13 at 18:33
  • Oh, I see. Yes, that much is clear. What would you suggest instead, assuming that my code would require qualifying very often? – idoby Jun 14 '13 at 18:41
  • 1
    @IBY: You can have `using` *declarations*, which would allow you to pick individual names (e.g. `using std::cout; cout << "Hello";`). Or if you think you really really need it, have a `using` directive like the one the OP has, but in the smallest possible scopes like the scope of a function, so that other modules including your header won't end up with that `using declaration std;` that brings all names from `std` into the global namespace – Andy Prowl Jun 14 '13 at 18:45
  • I see. Thank you. BTW, I'm not the OP. – idoby Jun 14 '13 at 18:46
2

You declared abc as extern but you never provided definition for it.

Try add definition inside main.cpp:

#include <iostream>
#include <vector>
#include "myClass.h"
#include "header.h"

using namespace std;
std::vector<myClass> abc; //^^add this line

int main(){
    abc.push_back(myClass(5));
    return 1;
}

However, IMHO using extern here in your code seems useless. Meanwhile, I don't think it is good to name a header file as header.h.

taocp
  • 23,276
  • 10
  • 49
  • 62
1

You have abc as a local variable. It should be a global variable. Only then extern would work.

But if you only want to access it as a local variable from within main() and not from another compiled CPP file/object, then it is pointless to use an extern. The extern is only needed if the variable is global and to be accessed from another compiled CPP/object.

ruben2020
  • 1,549
  • 14
  • 24
  • This isn't the issue, because the variable is defined as external only in main.cpp. He's not attempting to use it as a global from another unit. – idoby Jun 14 '13 at 18:24
  • Additional paragraph added. So, it seems extern is pointless. – ruben2020 Jun 14 '13 at 18:29