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.
My professor gave me two class header and .cpp files to build on. When I include these in main, they work fine. Whenever I just use his files, I get linker errors with clang and xcode.
Here's the error:
shannigan#mbp-007100 inheritance (master) $ make main
c++ main.cpp -o main
Undefined symbols for architecture x86_64:
"SavitchEmployees::SalariedEmployee::SalariedEmployee()", referenced from:
_main in main-0d7e27.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1
Here's my main:
#include "employee.h"
#include "salariedemployee.h"
#include <string>
#include <cstdlib>
#include <iostream>
using namespace SavitchEmployees;
using namespace std;
int main() {
cout << "Do I run?" << endl;
SalariedEmployee sam;
return 0;
};
The header file for Employee:
//This is the header file employee.h.
//This is the interface for the class Employee.
//This is primarily intended to be used as a base class to derive
//classes for different kinds of employees.
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include <string>
using std::string;
namespace SavitchEmployees
{
class Employee
{
public:
Employee( );
Employee(const string& theName, const string& theSsn);
string getName( ) const;
string getSsn( ) const;
double getNetPay( ) const;
void setName(const string& newName);
void setSsn(const string& newSsn);
void setNetPay(double newNetPay);
void printCheck( ) const;
protected:
string name;
string ssn;
double netPay;
};
}//SavitchEmployees
#endif //EMPLOYEE_H
The CPP file for main:
//This is the file: employee.cpp
//This is the implementation for the class Employee.
//The interface for the class Employee is in the header file employee.h.
#include <string>
#include <cstdlib>
#include <iostream>
#include "employee.h"
using std::string;
using std::cout;
namespace SavitchEmployees
{
Employee::Employee( ) : name("No name yet"), ssn("No number yet"), netPay(0)
{
//deliberately empty
}
Employee::Employee(const string& theName, const string& theNumber)
: name(theName), ssn(theNumber), netPay(0)
{
//deliberately empty
}
string Employee::getName( ) const
{
return name;
}
string Employee::getSsn( ) const
{
return ssn;
}
double Employee::getNetPay( ) const
{
return netPay;
}
void Employee::setName(const string& newName)
{
name = newName;
}
void Employee::setSsn(const string& newSsn)
{
ssn = newSsn;
}
void Employee::setNetPay (double newNetPay)
{
netPay = newNetPay;
}
void Employee::printCheck( ) const
{
cout << "\nERROR: printCheck FUNCTION CALLED FOR AN \n"
<< "UNDIFFERENTIATED EMPLOYEE. Aborting the program.\n"
<< "Check with the author of the program about this bug.\n";
exit(1);
}
}//SavitchEmployees
SalariedEmployees header:
//This is the header file salariedemployee.h.
//This is the interface for the class SalariedEmployee.
#ifndef SALARIEDEMPLOYEE_H
#define SALARIEDEMPLOYEE_H
#include <string>
#include "employee.h"
using std::string;
namespace SavitchEmployees
{
class SalariedEmployee : public Employee
{
protected:
double salary;//weekly
public:
SalariedEmployee( );
SalariedEmployee (const string& theName, const string& theSsn,
double theWeeklySalary);
double getSalary( ) const;
void setSalary(double newSalary);
void printCheck( );
};
}//SavitchEmployees
#endif //SALARIEDEMPLOYEE_H
SalariedEmployee.cpp:
//This is the file salariedemployee.cpp
//This is the implementation for the class SalariedEmployee.
//The interface for the class SalariedEmployee is in
//the header file salariedemployee.h.
#include <iostream>
#include <string>
#include "salariedemployee.h"
using std::string;
using std::cout;
using std::endl;
namespace SavitchEmployees
{
SalariedEmployee::SalariedEmployee( ) : Employee( ), salary(0)
{
//deliberately empty
}
SalariedEmployee::SalariedEmployee(const string& newName, const string& newNumber,
double newWeeklyPay)
: Employee(newName, newNumber), salary(newWeeklyPay)
{
//deliberately empty
}
double SalariedEmployee::getSalary( ) const
{
return salary;
}
void SalariedEmployee::setSalary(double newSalary)
{
salary = newSalary;
}
void SalariedEmployee::printCheck( )
{
setNetPay(salary);
cout << "\n__________________________________________________\n";
cout << "Pay to the order of " << getName( ) << endl;
cout << "The sum of " << getNetPay( ) << " Dollars\n";
cout << "_________________________________________________\n";
cout << "Check Stub NOT NEGOTIABLE \n";
cout << "Employee Number: " << getSsn( ) << endl;
cout << "Salaried Employee. Regular Pay: "
<< salary << endl;
cout << "_________________________________________________\n";
}
}//SavitchEmployees
How can I get rid of these linker errors so I can focus on my actual code? Is there anything obvious wrong? The only thing I've changed was making the "private" variables protected.
I can't see the class named SalariedEmployee.
I think the main function should look like this.
int main() {
cout << "Do I run?" << endl;
Employee sam;
return 0;
};
You have to use Employee instead of SalariedEmployee
Related
I'm trying to create a function below in my CreateReport class called load() that copies all the records (data) from my graduate.dat file into my static vector of Record pointers called primaryCollection. I created a Record class with variables that make up each Record, and in my load() function in createReport.cc I attempted to read each line in the file, create a Record object with each line, add it to my vector, and then print everything in primaryCollection.
The problem is every time I attempt to use primaryCollection, I keep getting the error:
CreateReport.o: In function `CreateReport::CreateReport()':
CreateReport.cc:(.text+0x43): undefined reference to `CreateReport::primaryCollection'
CreateReport.o: In function `CreateReport::load()':
CreateReport.cc:(.text+0x2ac): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x31d): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x32f): undefined reference to `CreateReport::primaryCollection'
I get 4 undefined references for the 4 times I mention primaryCollection in createReport.cc. I'm not sure if I'm initializing primaryCollection correctly and if that is whats causing these undefined references. I don't know if this is relevant to my problem, but CreateReport is also an abstract class and has a few subclasses called ReportOne, ReportTwo, etc.
primaryCollection is supposed to be a static vector of Record pointers and I'm also not allowed to use std::map for this task.
I would appreciate any help with this issue. I looked at this post Undefined reference to static variable c++ but I still don't really understand what to do. I'm not allowed to make global variables and I'm dealing with a collection rather than a single variable.
My graduate.dat file is formatted like below in the format < year province degree >
2000 AB Bachelor's
2005 AB Bachelor's
2005 MB College
Each line basically represents a Record. So the first record here is 2000 AB Bachelor's
EDIT: So I made changes to my code based on the comments by adding the line vector<Record*> CreateReport::primaryCollection; above my constructor, but it gives me the error:
CreateReport.cc:13:34: error: conflicting declaration ‘std::vector<Record*> CreateReport::primaryCollection’
vector<Record*> CreateReport::primaryCollection;
^~~~~~~~~~~~~~~~~
In file included from CreateReport.cc:5:0:
CreateReport.h:23:33: note: previous declaration as ‘std::vector<Record*>* CreateReport::primaryCollection’
static std::vector<Record*>* primaryCollection; //STL vector of record pointers
^~~~~~~~~~~~~~~~~
CreateReport.cc:13:34: error: declaration of ‘std::vector<Record*>* CreateReport::primaryCollection’ outside of class is not definition [-fpermissive]
vector<Record*> CreateReport::primaryCollection;
Any ideas how to fix this?
Record.h
#ifndef RECORD_H
#define RECORD_H
#include <iostream>
#include <string>
class Record{
public:
Record(int = 0, string = "", string = "");
~Record();
private:
int year;
string province;
string degree;
};
#endif
Record.cc
#include <iostream>
#include <string>
using namespace std;
#include "Record.h"
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
Record::~Record(){}
CreateReport.h
#ifndef CREATEREPORT_H
#define CREATEREPORT_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include "Record.h"
class CreateReport{
public:
CreateReport();
static void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
#endif
CreateReport.cc
#include <iostream>
using namespace std;
#include <string>
#include "CreateReport.h"
vector<Record*> CreateReport::primaryCollection;
CreateReport::CreateReport(){
}
void CreateReport::load(){
int year;
string province, degree;
ostream_iterator<Record*> outItr(cout);
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) { //as long as were not at end of file
Record* record = new Record(year, province, degree); //create Record object with this data
primaryCollection->push_back(record); //undefined reference
}
cout<<endl<<"List of Records:"<<endl;
copy(primaryCollection->begin(), primaryCollection->end(), outItr); //2 undefined references
}
Second version using `Record*` for `std::vector primaryCollection`.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
//***************** you need this line ********************
std::vector<Record*> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
Record *a = new Record(year, province, degree);
primaryCollection.push_back( a );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << *primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
Three major problems:
Using std::vector<*Record> cause many un-necessary difficulties;
For static member vector, a extra definition outside the class is necessary.std::vector<Record> CreateReport::primaryCollection;. This erases the undefined error message.
Using copy to std::cout doesn't work, it provide no method of printing Record. Suggest to write a output overload.
Based on these, I provide a version as follows (mixed all headers together.)
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record> primaryCollection;
};
//***************** you need this line ********************
vector<Record> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
primaryCollection.push_back( Record(year, province, degree) );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
Edit: I had forgotten to explicitly define my class destructors in their respective .cpp files. I replaced *p with string *killList = new string[10];
and my code now compiles. Thanks for your replies!
I've tried to compile the following files using the command :
g++ -o hunter hunter_h.h hunter_h.cpp animal_h.h animal_h.cpp main.cpp
animal_h.h
#include <iostream>
#include <string>
#ifndef ANIMAL_H
#define ANIMAL_H
using namespace std;
// Animal class
class animal
{
friend class hunter;
// need a name, species, private ID
public:
animal();
animal(string aSpecies);
string name;
string species;
string getSpecies();
void setName(string aName);
string getName();
int getID();
~animal();
private:
static int uID;
};
#endif
animal_h.cpp
#include "animal_h.h"
//#include "hunter_h.h"
#include <iostream>
#include <string>
using namespace std;
int animal:: uID = 0 ;
animal::animal()
{
cout << "Created an animal!" << endl;
name = "?";
species = "?";
uID++;
}
animal::animal(string aSpecies)
{
cout << "Created 1 "<< aSpecies << "!" << endl;
name= "?";
species = aSpecies;
uID++;
}
string animal::getSpecies()
{
cout << species << endl;
}
void animal::setName(string aName)
{
name = aName;
cout << "This " << species << " is now called " << name << endl;
}
string animal::getName()
{
cout << name << endl;
}
int animal:: getID()
{
cout << uID << endl;
}
hunter_h.h This is a derived class of the animal base class with unique behaviors.
#include "animal_h.h"
#include <iostream>
#ifndef ANIMAL_HUNTER
#define ANIMAL_HUNTER
class hunter : public animal
{
public:
hunter();
hunter(std::string aSpecies);
void recordKills(std::string kill);
static int tKills;
int totalKills();
static std::string *theKills();
static std::string *p;
static int clearTotal();
~hunter();
};
#endif
hunter_h.cpp
#include "animal_h.h"
#include "hunter_h.h"
#include <iostream>
#include <string>
using namespace std;
int hunter:: tKills =0;
string killList[10];
hunter::hunter()
{
cout<<"created a hunter! "<<endl;
name= "? ";
species="? ";
string *p;
p = &killList[0];
}
hunter::hunter(string aSpecies)
{
name = "?";
species = aSpecies;
cout << "created a hunting "<<species <<endl;
}
string *theKills()
{
return hunter::p;
}
void hunter::recordKills(string kill)
{
cout << kill << " killed." << endl;
*(p+tKills) = kill;
tKills++;
cout << tKills << " total kills." << endl;
}
int hunter::totalKills()
{
cout << name << "'s " << "Total kills: " << tKills << endl;
}
int hunter::clearTotal()
{
delete[] killList;
return 0;
}
main.cpp
#include "animal_h.h"
#include "hunter_h.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
hunter *hunterC;
hunterC= new hunter("cheetah");
hunterC->recordKills("Mouse");
hunterC-> recordKills("Gazelle, Gazelle");
hunterC-> recordKills("Hyena");
hunterC-> recordKills("Rabbit, Rabbit");
hunterC->theKills;
hunterC->clearTotal;
}
Now, when I try to compile I get the following warning and errors:
hunter_h.cpp: In static member function ‘static int hunter::clearTotal()’:
hunter_h.cpp:49:11: warning: deleting array ‘killList’
delete[] killList;
^
/tmp/ccnv8xdj.o:hunter_h.cpp:(.text+0x71): undefined reference to `animal::~animal()'
/tmp/ccnv8xdj.o:hunter_h.cpp:(.text+0x101): undefined reference to `animal::~animal()'
/tmp/ccnv8xdj.o:hunter_h.cpp:(.text+0x119): undefined reference to `hunter::p'
/tmp/ccnv8xdj.o:hunter_h.cpp:(.text+0x15a): undefined reference to `hunter::p'
/tmp/ccqCD1e7.o:main.cpp:(.text+0x1f4): undefined reference to `animal::~animal()'
/tmp/ccqCD1e7.o:main.cpp:(.text+0x20c): undefined reference to `animal::~animal()'
collect2: error: ld returned 1 exit status
I've been learning C++ for a couple months only so am not sure where the above code is going wrong. How can I get this to compile and run?
killList is not allocated using new[], then dont delete it with delete[]. It is not allocated runtime, then it does not have to be deallocated explicitly. It will release its memory when the program exits. With your code as it is you are running the chance of overrunning you killList array.
Try using std::vector instead.
std::vector<std::string> killList;
...
void recordKills(std::string s)
{
...
killList.push_back(s);
}
void clearTotal()
{
killList.clear();
}
Im trying to create a very simple VCard but im getting a non-const lvalue reference to type cannot bind error in my main.cpp and can't figure this out. the problem line is.....
vc->createVCard("JasonSteindorf.vcf", &p1);
//Person.h
#ifndef JASONSTEINDORF_PERSON_H
#define JASONSTEINDORF_PERSON_H
#include <string>
using std::string;
namespace JasonSteindorf{
class Person{
public:
Person();
Person(string firstName,string lastName,string phoneNumber,string email)
: firstName(firstName), lastName(lastName), phoneNumber(phoneNumber), email(email){}
inline string getFirstName(){ return firstName; }
inline string getLastName(){ return lastName; }
inline string getPhoneNumber(){ return phoneNumber; }
inline string getEmail(){ return email; }
private:
string firstName, lastName, phoneNumber, email;
};
}
#endif
//VCard.h
#ifndef JASONSTEINDORF_VCARD_H
#define JASONSTEINDORF_VCARD_H
#include "Person.h"
#include <string>
using std::string;
namespace JasonSteindorf{
class VCard{
public:
void createVCard(string fileName, Person &p);
string getVCard(Person &p);
};
}
#endif
//VCard.cpp
#include "VCard.h"
#include <fstream>
using std::ofstream;
#include <string>
using std::string;
#include <sstream>
#include <iostream>
using std::ostringstream;
using namespace JasonSteindorf;
//Writes the VCard to a file
string getVCard(Person &p){
ostringstream os;
os << "BEGIN:VCARD\n"
<< "VERSION:3.0\n"
<< "N:" << p.getLastName() << ";" << p.getFirstName() << "\n"
<< "FN:" << p.getFirstName() <<" " << p.getLastName() << "\n"
<< "TEL:TYPE=CELL:" << p.getPhoneNumber() << "\n"
<< "EMAIL:" << p.getEmail() << "\n"
<< "URL:" << "http://sorcerer.ucsd.edu/html/people/jason.html" << "\n"
<< "REV:20110719T195243Z" << "\n"
<< "END:VCARD\n";
return os.str();
}
//Returns a string containing the VCard format
void createVCard(string fileName, Person &p){
string vCard = getVCard(p);
ofstream outputFile("/Users/jsteindorf/Desktop/" + fileName);
outputFile << vCard;
}
//main.cpp
#include "Person.h"
#include "VCard.h"
#include <iostream>
using namespace JasonSteindorf;
int main(int argc, const char * argv[])
{
VCard *vc = new VCard();
Person *p1 = new Person ("Jason", "S", "858-555-5555", "js#ucsd.edu");
vc->createVCard("JS.vcf", &p1);
return 0;
}
You haven't defined the functions createVCard and getCard as member functions of VCard class.
Those are global functions. Use the scope resolution operator :: to define them as member functions of the class like
void Vcard::createVCard(string fileName,Person &p)
{
....
....
}
string Vcard::getVCard(Person &p)
{
....
....
}
And also your createVCard function accepts a reference to Person hence you will have to pass the object to the person not the address of pointer to the object (&p) nor address of the object (p) instead pass the object by de-referencing it like *p, hence the call would look like vc->createVCard("JS.vcf", *p1)
I am getting a linker error undefined reference to Person::Person when trying to implement my program. The three parts are below. I have been working on fixing it for a few hours now. I know it's probably something simple that I am just not seeing. But I have looked around on the internet and still have not found my answer. So any help would be appreciated.
#ifndef PERSON0_H_
#define PERSON0_H_
#include <string>
class Person // class declaration
{
private:
static const int LIMIT = 25;
std::string lname;
char fname[LIMIT];
public:
Person() {lname = ""; fname[0] = '\0';}
Person(const std::string & ln, const char * fn = "Hay you");
void Show() const;
void FormalShow() const;
};
#endif
#include <iostream>
#include <string>
#include "person0.h"
void Person::Show() const
{
using namespace std;
std::cout << fname << " " << lname << '\n';
}
void Person::FormalShow() const
{
using std::cout;
std::cout << lname << ", " << fname << '\n';
}
#include <iostream>
#include <string>
#include "person0.h"
int main()
{
using namespace std;
Person one;
Person two("Smythecraft");
Person three("Dimwiddy", "Sam");
one.Show();
cout << endl;
one.FormalShow();
cout << endl;
two.Show();
cout << endl;
two.FormalShow();
cout << endl;
three.Show();
cout << endl;
three.FormalShow();
cin.get();
cin.get();
return 0;
}
I am not really a C++ person, so the terminology might be wrong, but I would say that the implementation of the
Person::Person(const std::string & ln, const char * fn)
constructor is missing.
Keep getting these errors while trying to compile an c++ class program.
testStock.cpp: In function ‘int main()’: testStock.cpp:8: error:
‘Stock’ was not declared in this scope testStock.cpp:8: error:
expected ;' before ‘first’ testStock.cpp:9: error: ‘first’ was not
declared in this scope testStock.cpp:12: error: expected;' before
‘second’ testStock.cpp:13: error: ‘second’ was not declared in this
scope
stock.h
#ifndef STOCK_H
#define STOCK_H
using namespace std;
class Stock
{
private:
string symbol;
string name;
double previousClosingPrice;
double currentPrice;
public:
Stock(string symbol, string name);
string getSymbol() const;
string getName() const;
double getPreviousClosingPrice() const;
double getCurrentPrice() const;
double changePercent();
void setPreviousClosingPrice(double);
void setCurrentPrice(double);
};
#endif
stock.cpp
#include <string>
#include "stock.h"
Stock::Stock(string symbol, string name)
{
this->symbol = symbol;
this->name = name;
}
string Stock::getSymbol() const
{
return symbol;
}
string Stock::getName() const
{
return name;
}
void Stock::setPreviousClosingPrice(double closing)
{
previousClosingPrice = closing;
}
void Stock::setCurrentPrice(double current)
{
currentPrice = current;
}
double Stock::getPreviousClosingPrice() const
{
return previousClosingPrice;
}
double Stock::getCurrentPrice() const
{
return currentPrice;
}
double Stock::changePercent()
{
return ((currentPrice - previousClosingPrice)/previousClosingPrice) * 100;
}
testStock.cpp
#include <string>
#include <iostream>
#include "string.h"
using namespace std;
int main()
{
Stock first("aapl", "apple");
cout << "The stock symbol is " << first.getSymbol() << " and the name is " << first.getName() << endl;
first.setPreviousClosingPrice(130.0);
first.setCurrentPrice(145.0);
Stock second("msft", "microsoft");
second.setPreviousClosingPrice(30.0);
second.setCurrentPrice(33.0);
first.changPercent();
second.changePercent();
cout << "The change in percent for " << first.getName << " is " << first.changePercent() << endl;
cout << "The change in percent for " << second.getName << " " << second.getSymbol() << " is " << second.changePercent() << endl;
return 0;
}
Im sure its something obvious but its only my second class program.
It looks like you have omitted
#include "stock.h"
from your testStock.cpp.
Compiler tells you "‘Stock’ was not declared in this scope ". So you should ask yourself "Where is 'Stock' declared?" and you should be able to answer it: "It's declared in stock.h".
And "Why compiler doesn't know that 'Stock' is declared in stock.h?" Because you haven't included it. So as it was mentioned here already, #include "stock.h" is the solution.
Hope you will spend more time reading compilers errors / warnings and also more time trying to understand them ;)
You are just not including "stock.h" in your main file, so the compiler doesn't know what Stock first means.
#include "stock.h"
and you will be able to create Stock object as it will be visible to your TestStock class.