This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I am making a program with a list of baby names but I've decided to make a seperate function to open the file, this is what I have got so far.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void open_file(ifstream& in, char fileName[]);
void find_name(ifstream& in, string name, int numNames);
int main() {
const int NUMNAMES = 1000;
ifstream inStream;
char fileName[30];
string name;
cout << "Enter the name of the file that contains the names: " << endl;
open_file(inStream, fileName);
cout << "Enter the name to search for (capitalize first letter): " << endl;
cin >> name;
find_name(inStream, name, NUMNAMES);
inStream.close();
}
void open_file(ifstream& ) {
string line;
ifstream myfile ("babyNames.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "I/O failure opening file babyNames";
}
Does anyone know why I am getting so many error messages:
Undefined symbols for architecture x86_64:
"find_name(std::__1::basic_ifstream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int)", referenced from:
_main in Untitled-1b6d2e.o
"open_file(std::__1::basic_ifstream<char, std::__1::char_traits<char> >&, char*)", referenced from:
_main in Untitled-1b6d2e.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Does anyone know what I am doing wrong, I feel like it is relatively close I'm just fairly new to streams in c++.
The shown code declares and calls the following functions:
void open_file(ifstream& in, char fileName[]);
void find_name(ifstream& in, string name, int numNames);
Unfortunately, the shown code does not define any of these two functions, and the two linking errors are the result of that.
The shown code does define some function that's also called open_file(), but it's a completely different function because it takes different parameters. The shown code does not define any function called find_name().
You cannot simply declare a function like:
void open_file(ifstream& in, char fileName[]);
And then expect the code for this function to automatically appear somewhere. You have to define, and write the contents of this function. The parameters in this function, when you define it, must be the same as what you declared here.
Related
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
So for class we are learning about OOP in C++, and I built my class but every time I try to compile it I get this error message:
Undefined symbols for architecture x86_64:
"Player::set_assits(int)", referenced from:
_main in playerDataBase-666bbb.o
"Player::set_last_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in playerDataBase-666bbb.o
"Player::set_team_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in playerDataBase-666bbb.o
"Player::set_first_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in playerDataBase-666bbb.o
"Player::set_year_of_birth(int)", referenced from:
_main in playerDataBase-666bbb.o
"Player::set_goals(int)", referenced from:
_main in playerDataBase-666bbb.o
"Player::Player()", referenced from:
_main in playerDataBase-666bbb.o
"Player::~Player()", referenced from:
_main in playerDataBase-666bbb.o
ld: symbol(s) not found for architecture x86_64
I can't understand why this happens, I have tried to run this by compiling separate .h, and .cpp files as well as by putting the class, and main function inside of the same .cpp file. Any help would be appreciated as well here is my code.
#include <iostream>
#include <string>
using namespace std;
class Player{
public:
Player();
~Player();
// accessors and mutators
void set_first_name(string in_first_name);
string first_name();
void set_last_name(string in_last_name);
string last_name();
void set_team_name(string in_team_name);
string team_name();
void set_year_of_birth(int in_year_of_birth);
int year_of_birth;
void set_goals(int in_goals);
int goals;
void set_assits(int in_assists);
int assists;
//methods
void display();
private:
string first_name_;
string last_name_;
string team_name_;
int year_of_birth_;
int goals_;
int assits_;
};
void Player::display(){
cout << first_name_ << last_name_ << endl;
}
int main(){
Player player;
player.set_first_name("John");
player.set_last_name("Tedesco");
player.set_team_name("Blyth Warriors");
player.set_year_of_birth(2002);
player.set_goals(2);
player.set_assits(7);
player.display();
}
Thanks for any help and sorry again for messy / poor code.
Thanks,
John
None of these methods are defined, only declared:
Player();
~Player();
// accessors and mutators
void set_first_name(string in_first_name);
string first_name();
void set_last_name(string in_last_name);
string last_name();
void set_team_name(string in_team_name);
string team_name();
void set_year_of_birth(int in_year_of_birth);
void set_goals(int in_goals);
void set_assits(int in_assists);
You need to provide reasonable definitions for these methods. Right now, you tell the compiler you will provide a definition for each of these methods, and never do. For default constructors, you may use Player() = default;, if you want the compiler to generate a constructor.
For example, to define the first_name property, you may do:
void Player::set_first_name(const string& in_first_name)
{
first_name_ = in_first_name;
}
const string& first_name() const
{
return first_name_;
}
Please note I've changed this to take value by constant reference, and return a value by constant reference, rather than by value, for efficiency reasons.
You declared all those fancy methods, e.g:
void set_first_name(string in_first_name);
string first_name();
But you never defined them!
Implement them, and it will work, e.g:
void set_first_name(string in_first_name) {
first_name_ = in_first_name;
}
string first_name() {
return first_name_;
}
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
Can someone please explain to me why the following won't compile?, and hopefully the obvious thing that I have missed...
functions.hpp:
template<typename T> string vector_tostr(std::vector<T> v);
functions.cpp:
template<typename T> string vector_tostr(std::vector<T> v){
std::stringstream ss;
std::string thestring = "";
if(v.size() > 0){
ss << "[";
for(size_t i = 0; i < v.size(); i++){
if(i != 0)
ss << " ";
ss << v[i];
}
ss << "]";
thestring = ss.str();
}
return thestring;
}
main.cpp
#include "functions.hpp"
int main(int argc, char *argv[]){
vector<int> thevector;
thevector.push_back(1);
thevector.push_back(2);
string result = vector_tostr(thevector);
//I have also tried vector_tostr<int>(thevector)
}
The cryptic error I am getting as follows:
Undefined symbols for architecture x86_64: "std::basic_string, std::allocator >
vector_tostr(std::vector >)", referenced
from:
_main in main.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status make: * [main] Error 1
You are not allowed to seperate the declaration and definition of a templated function in the same way that you would a normal function (declaration in '.hpp' file, definition in '.cpp' file). There are a couple of ways you can get around that.
You can declare AND define the function in the same place in the header file.
OR
You could try this, in a file called functions.inl:
template<typename T>
inline string vector_tostr(std::vector<T> v){
std::stringstream ss;
std::string thestring = "";
if(v.size() > 0){
ss << "[";
for(size_t i = 0; i < v.size(); i++){
if(i != 0)
ss << " ";
ss << v[i];
}
ss << "]";
thestring = ss.str();
}
return thestring;
}
Then, at the end of the header file (functions.hpp), type this in:
#include "functions.inl"
.inl is the file extension for the inline header file. You can use this to seperate the declaration
and definition of templated functions.
Templates are instantiated in compile time. What the compiler does is create one overloaded method for each template argument value that is used in the code. For example, using int and double as template argument will create two overloaded methods from the same definition, only vary in argument type. So compiler must be able to see the definition while compiling. You can do this in several ways
Fully defined in header
Defined in for ex. .impl file and include it in the declaring header
Explicitly instantiated with template parameter in a .cpp file, in that case only the instantiated versions can be used.
You need to have the implementation of the function template visible where it's used. Otherwise, the compiler doesn't know how to instantiate the function given a type.
Put the function definition in functions.hpp. There is no use of functions.cpp.
I tried compiling a simple program on Xcode and got the following messages:
function<anonymous namespace>::Initialize' has internal linkage but is not defined
function<anonymous namespace>::HandleBadInput' has internal linkage but is not defined
Undefined symbols for architecture x86_64:
"(anonymous namespace)::Initialize()", referenced from:
_main in main.o
"(anonymous namespace)::HandleBadInput()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The header file looks like this:
#ifndef WJKErrorHandling
#define WJKErrorHandling
namespace WJKErrorHandling{
void Initialize(void);
int HandleBadInput(void);
}
#endif // defined(WJKErrorHandling)
the implementation file looks like this:
#include <iostream>
#include "WJKErrorHandling.h"
namespace WJKErrorHandling{
void Initialize(void){
std::cin.exceptions(std::cin.failbit);
}
int HandleBadInput(void){
std::cerr << "Input Error: wrong type?\n";
std::cin.clear();
char BadInput[5];
std::cin >> BadInput;
return 1;
}
}
and main.cpp looks like this:
#include <iostream>
#include "WJKErrorHandling.h"
void Prompt (void){
//Prompts the user to begin entering numbers
std::cout << "Begin entering numbers: \n";
}
float GetNumber (void){
std::cout << "Number: \n";
float Number;
std::cin >> Number;
return Number;
}
std::string GetString (void){
std::cout << "String: \n";
std::string String;
std::cin >> String;
return String;
}
int main()
{
Prompt();
WJKErrorHandling::Initialize();
int ReturnCode = 0;
try{
float Number = GetNumber();
std::cout << Number;
std::string String = GetString();
std::cout << String;
std::cout << "SUCCESS!!!!\n";
}
catch(...){
ReturnCode = WJKErrorHandling::HandleBadInput();
}
return ReturnCode;
}
I've tried finding an answer so far, but I haven't understood any of the posts that I've found. I'm new with C++, so any help would be greatly appreciated!
Your #define Guard is causing name lookup issue.
change to below style should fix the issue:
#ifndef WJK_ERROR_HANDLING_H
#define WJK_ERROR_HANDLING_H
You could also use the non-standard but more idiomatic #pragma once, according to its wikipedia page it is supported by all major compilers.
Since many compilers have optimizations to identify include guards, there is no speed advantage between the two. For myself I see the following advantages of #pragma once:
It has only one meaning (whereas defines serve different purposes) and will not clash with other things (e.g. a namespace as in your case).
It is little to type and simple to remember.
You cannot have errors due to a typo (WJKERRORHANDLNG_H, ups and I is missing), because you started the header as a copy of another and forgot to change the include guard, which gives you rather nasty bughunting sessions.
This turns out to be a bad include guard:
#ifndef WJKErrorHandling
#define WJKErrorHandling
because you later try to use WJKErrorHandling as a namespace, but the macro makes it go away.
Change your include guard to something like:
#ifndef WJKERRORHANDLING_H
#define WJKERRORHANDLING_H
which is probably more idiomatic and less likely to conflict with something.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm getting stranger error when I compile my code. I guess the header files aren't being properly linked because every single one of those variables that are erroring have been specified in 'variables.h' which I properly #include. Strangely enough, if I comment ou the areas in which the variables are used in main.cpp, a whole other slew of errors pop up of the same variables in another file readfile.cpp. Below is the error output, as well as my code for main.cpp and variables.h. Any ideas?
g++ -c main.cpp
g++ -c readfile.cpp
g++ -c Objects.cpp
g++ -o raytracer main.o readfile.o Objects.o
Undefined symbols for architecture x86_64:
"_depth", referenced from:
init() in main.o
readFile(char const*)in readfile.o
"_diffuse", referenced from:
readFile(char const*)in readfile.o
"_emission", referenced from:
readFile(char const*)in readfile.o
"_filename", referenced from:
init() in main.o
"_fov", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_height", referenced from:
init() in main.o
readFile(char const*)in readfile.o
"_lookatx", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_lookaty", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_lookatz", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_lookfromx", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_lookfromy", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_lookfromz", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_maxvertnorms", referenced from:
init() in main.o
readFile(char const*)in readfile.o
"_maxverts", referenced from:
init() in main.o
readFile(char const*)in readfile.o
"_shininess", referenced from:
readFile(char const*)in readfile.o
"_specular", referenced from:
readFile(char const*)in readfile.o
"_spherecount", referenced from:
init() in main.o
"_spheres", referenced from:
readFile(char const*)in readfile.o
"_triangles", referenced from:
readFile(char const*)in readfile.o
"_tricount", referenced from:
init() in main.o
"_trinormals", referenced from:
readFile(char const*)in readfile.o
"_trinormcount", referenced from:
init() in main.o
"_upx", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_upy", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_upz", referenced from:
init() in main.o
initCamera(float*)in readfile.o
"_vertexcount", referenced from:
init() in main.o
"_vertexnormcount", referenced from:
init() in main.o
"_vertices", referenced from:
readFile(char const*)in readfile.o
"_vertnormals", referenced from:
readFile(char const*)in readfile.o
"_width", referenced from:
init() in main.o
readFile(char const*)in readfile.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Below is variables.h..
#include "vertexnormal.h"
#include "sphere.h"
#include "tri.h"
#include "trinormal.h"
#include "vec.h"
#include <string>
#include <vector>
using namespace std;
// width and height specify image size
extern float width;
extern float height;
// maximum depth for a ray (level of recursion)
extern int depth;
// the output file to which the image should be written
extern string filename;
// camera specifiations (should i put in a struct?)
extern float lookfromx;
extern float lookfromy;
extern float lookfromz;
extern float lookatx;
extern float lookaty;
extern float lookatz;
extern float upx;
extern float upy;
extern float upz;
extern float fov;
//***************************//
// Geometry Specifications //
//***************************//
// specifies the number of vertrices for tri specifications
extern int maxverts;
// specifies the number of vertices with normals for tri specifications
extern int maxvertnorms;
// pile of inputted vertices
// might need to #include glm file
extern vector<vec> vertices;
// pile of inputted vertices with specified normals
extern vector<vertexNormal> vertnormals;
// pile of inputted spheres
extern vector<sphere> spheres;
// pile of inputted triangles
extern vector<tri> triangles;
// pile of inputted triangles using vertices with specified normals
extern vector<triNormal> trinormals;
extern int vertexcount;
extern int vertexnormcount;
extern int spherecount;
extern int tricount;
extern int trinormcount;
//**************************//
// Materials Specifiations //
//**************************//
extern float diffuse[3];
extern float specular[3];
extern float shininess;
extern float emission[3];
And here is my main.cpp,
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include "Objects.h"
using namespace std;
#include "readfile.h"
#include "variables.h"
void init() {
cout << "Reading in scene file... \n";
cout << "Image size has been set to a " << width << " x " << height << " output. /n";
cout << "The maximum recursion depth has been set to " << depth << ". \n";
cout << "The image will be output to " << filename << ".png. \n";
cout << "The camera has been instantiated with the following properties: \n";
cout << "\t POSITION: (" << lookfromx << ", " << lookfromy << ", " << lookfromz << ") \n";
cout << "\t DIRECTION: (" << lookatx << ", " << lookaty << ", " << lookatz << ") \n";
cout << "\t UP: (" << upx << ", " << upy << ", " << upz << ") \n";
cout << "\t FIELD OF VIEW: " << fov << " \n";
cout << "An amount of " << vertexcount << " vertices has been specified with a maximum of " << maxverts << " allowed. \n";
cout << "An amount of " << vertexnormcount << " vertices with normals has been specified with a maximum of " << maxvertnorms << " allowed. \n";
cout << "An amount of " << spherecount << " spheres have been specified. \n";
cout << "An amount of " << tricount << " triangles have been specified. \n";
cout << "An amount of " << trinormcount << " triangles with calculated vertex normals have been specified. \n";
}
int main (int argc, char * argv[]) {
readFile(argv[1]);
init();
return 0;
}
Try this:
Open up your variables.h header file.
Copy ALL of the extern variable declarations.
Open up your main.cpp file.
Paste all your declarations copied from (2).
In the same main.cpp remove the keyword extern from each declaration.
Save all your files.
Lookup how extern works. Something tells me you missed that in your studies.
Ok, this has been covered in SO what, a few thousand times, but for the OP:
Declaring the Existence of a Variable
// DECLARE myvar, an int variable. no storage has been set aside
// this is simply telling the compiler this thing exists.. somewhere.
extern int myvar;
Defining The Existence of a Variable
// DEFINE myvar, an int variable. storage *is* set aside here.
// only ONE of these, by this name, can be in your global
// namespace in your program.
int myvar = 0;
Traditionally, extern declarations are in headers, but definitions are always in c/cpp files. There must be a matching definition for any extern-declared variable that is used in your program.
How this fits with your situation
All of your variables were declared in variables.h, but the were never defined anyway. By telling you to copy/paste all those declarations into a source file (any will do; I chose main.cpp because it was already in your project), and then removing the extern keyword in that source file (not the header), you were essentially defining where they all officially existed. Now all those references to extern'ed variables in your other source files finally have something to hook up to at link time.
Sidebar
In the c/cpp file where your variables are being defined, make sure you initialize them to proper values. This is the one and only place you can do it. you can NOT do it on any extern declaration. It can only be done on a definition.
Header File
extern int myvar; // note: no initial value.
Source File
int myvar = 0; // note: initialized to zero (0)
I hope that made at least a little sense.
extern float lookfromx;
extern float lookfromy;
extern float lookfromz;
extern float lookatx;
extern float lookaty;
extern float lookatz;
These are simply declarations. You need to define these variables somewhere in the program (in variables.cpp, for example). To make these definitions you can either
remove the extern keyword
add an initialiizer ( = value; )
Your variable.h file simply makes your variables portable across other files in the global scope, but they still need to be declared. Make sure to declare the actual variables in your main file(normal method of initialization).
The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default.
Read more on the extern keyword
It seems like my two files, userinterface.h
#ifndef USERINTERFACE_H
#define USERINTERFACE_H
#include <string>
#include "vocabcollection.h"
namespace user_interface
{
//Finds a file
//
//Returns when user selects a file
std::string findFile();
//more comments followed by functions
}
#endif
and userinterface.cpp,
#include "userinterface.h"
using namespace std;
using namespace user_interface;
string findFile()
{
return "./";
}
//more placeholder implementations of such functions; void functions have nothing within
//the brackets
are giving me this slew of errors from the linker:
Undefined symbols for architecture x86_64:
make: Leaving directory `longdirectorypath'
"user_interface::showTestResults(int, int)", referenced from:
vocabCollection::test() in vocabcollection.o
"user_interface::get(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
addNewCollection() in mainlogic.o
loadNewCollection() in mainlogic.o
"user_interface::findFile()", referenced from:
loadNewCollection() in mainlogic.o
"user_interface::displayMainMenu(std::vector<vocabCollection, std::allocator<vocabCollection> >)", referenced from:
mainlogic() in mainlogic.o
"user_interface::getUserAction()", referenced from:
mainlogic() in mainlogic.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [cheapassVocab.app/Contents/MacOS/cheapassVocab] Error 1
The process "/usr/bin/make" exited with code 2.
Error while building project cheapassVocab (target: Desktop)
When executing build step 'Make'
What's happening here?
In the header file, you declare the function findFile in the namespace user_interface. In the cpp file the free function findFile is defined. Yes, you are using namespace user_interface, but the compiler doesn't know that the findFile defined there belongs to namespace user_interface. The result of all this is that you've declared user_interface::findFile and defined ::findFile. When you call user_interface::findFile, the linker cannot find it, since there's only the free function findFile.
Easily solved - cpp file:
#include "userinterface.h"
using namespace std;
namespace user_interface
{
string findFile()
{
return "./";
}
}
You cannot implement findFile like that; it really has to go in the namespace:
namespace user_interface
{
string findFile()
{
return "./";
}
}
or:
string user_interface::findFile()
{
return "./";
}
The using directive is only for lookup, not for definitions - imagine what using namespace std; would do to all your function definitions otherwise!
You are defining findFile in the wrong namespace.
Either
std::string user_interface::findFile()
{
return "./";
}
or
namespace user_interface
{
std::string findFile()
{
return "./";
}
}
using does not affect where names are defined, it only affects how names are looked up.