1

I get this error when i build the program: Apple Mach-O Linker (ld) Error Linker Command failed with exit code 1. Usually when I try to fix this error, its because the file with the main function is #include-ing a file more than once. However, I do not believe that that is the case this time. I am also notified by X Code that the duplicate symbol _passed in: ranker.o and olympic.o.

//competitor.h

#ifndef __Olympic_Lab__competitor__
#define __Olympic_Lab__competitor__

#include <iostream>
using namespace std;
 class Competitor {
     char* name = nullptr;
     int laneAssignment;    
     float time;
 public:
    Competitor(char n[], int lane);
    ~Competitor();
    void setTime(float f);
    char* getName(){    return name;    }
    int getLane(){      return laneAssignment;    }
    float getTime(){    return time;    }
    void print(){   cout << name << endl;    }
 };
#endif 

//competitor.cpp

#include "competitor.h"
Competitor::Competitor(char n[], int lane){
    name = n;
    laneAssignment = lane;
}
Competitor::~Competitor(){
    //does nothing for now
}
void Competitor::setTime(float t){
    time = t;
}

//ranker.h

#ifndef __Olym__ranker__
#define __Olym__ranker__
#include <vector>
#include "competitor.h"
using namespace std;
int passed = 0;
class Ranker {
    bool boolean = true;
public:
    vector<Competitor*> rv;
    Ranker(int lanes);
    ~Ranker();
    int addList(Competitor* c);
    Competitor* getLane(int lane);
    Competitor* getFinish(int finish);
    int getFilled();
};
#endif

//ranker.cpp

#include "ranker.h"
Ranker::Ranker(int lan){
    rv.resize(lan - 1);
    for(int i = 0; i <= rv.size(); i++){
        rv[i] = nullptr;
    }
}
Ranker::~Ranker(){
    for(int i = 0; i <= rv.size(); i++){
        delete rv[i];
    }
}
int Ranker::addList(Competitor *c){
    if(c != NULL && passed <= 4){
        rv[passed++] = c;
        return passed - 1;
    }
    return 0;
}
 Competitor* Ranker::getLane(int lane){
    for(int i = 0; i <= rv.size(); i++){
        if(rv[i]->getLane() == lane && rv[i] != NULL){
            return rv[i];
        }
    }
    return rv[0];
}
Competitor* Ranker::getFinish(int finish){
    if(boolean){
        Competitor *temp = nullptr;
        int highestIndex;
        for(int i = rv.size(); i >= 0; i--){
            highestIndex = i;
            for(int j = i; j >= 0; j--){
                if(rv[j] != nullptr && rv[highestIndex] != nullptr){
                    if(rv[j]->getTime() > rv[highestIndex]->getTime())
                        highestIndex = j;
                }
            }
            temp = rv[i];
            rv[i] = rv[highestIndex];
            rv[highestIndex] = temp;   
        }
        delete temp;
        temp = *new Competitor*;
        boolean = false;
    }
    return rv[finish - 1];
}
int Ranker::getFilled(){
    int filled = 0;
    for(int i = 0; i <= rv.size(); i++){
        if(rv[i] != NULL){
            filled++;
        }
    }
     return filled;
}

//olympic.h

#ifndef _Olympic_Lab__olympic__
#define _Olympic_Lab__olympic__
#include "ranker.h"
#endif

//olympic.cpp

#include "olympic.h"

 int main(){
    const int lanes = 4;
    Ranker rank(lanes);
    Competitor* starters[4];
    starters[0] = new Competitor("EmmyLou Harris", 1);
    starters[1] = new Competitor("Nanci Griffith", 2);
    starters[2] = new Competitor("Bonnie Raitt", 3);
    starters[3] = new Competitor("Joni Mitchell", 4); 
    starters[0]->setTime((float)12.0);
    starters[1]->setTime((float)12.8);
    starters[2]->setTime((float)11.0);
    starters[3]->setTime((float)10.3);
    for(int i = 0; i < lanes; i++){
        rank.addList(starters[i]);
    }
    cout << "Competitors by lane are:" << endl;
    for(int i = 1; i <= lanes; i++)
        rank.getLane(i)->print();
    cout << "Rankings by finish are:" << endl;
    for(int i = 1; i <= lanes; i++)
        rank.getFinish(i)->print();
    for(int i = 0; i < lanes; i++){
        delete starters[i];
    }
}

It would be appreciated if someone could assist me in finding exactly what causes this error. Thanks!

Some One
  • 35
  • 5

1 Answers1

1

If you declare a variable in a header it will be duplicated in every file that includes the header.

So int passed = 0; in ranker.h is going to give you a lot of grief. ranker and olympian both have allocated a different passed and the linker now has no clue which one is the real passed.

So what you probably want is

extern int passed;

in ranker.h to declare that passed will exist at some point, if it doesn't yet, so it doesn't need to be allocated. The compiler will happily carry on and allow you to use passed.

And then in ranker.cpp, declare

int passed = 0;

to allocate passed and satisfy the linker. Now you have only one passed and anyone who includes ranker.h can see and use it.

If you want more than one passed, you have to do something else so that they don't share the same name and scope, but this doesn't look like your goal.

Off topic: resist the urge to put using namespace std;in a header file. It can lead to future problems that can be very hard to debug. More here: Why is "using namespace std" considered bad practice?

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54