2016-08-02 2 views
1

Я получаю эту ошибку при создании программы: Apple Mach-O Linker (ld) ErrorLinker Command failed with exit code 1. Обычно, когда я пытаюсь исправить эту ошибку, ее потому, что файл с основной функцией #include -в файле более одного раза. Однако я не верю, что на этот раз это так. Я также уведомил X-код, что duplicate symbol _passed in:ranker.o и olympic.o.Почему у моего кода есть «ошибка компоновщика Apple Mach-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]; 
    } 
} 

Было бы понятно, если бы кто-то может помочь мне в поиске точно, что вызывает эту ошибку. Благодаря!

ответ

1

Если вы объявите переменную в заголовке, она будет дублироваться в каждом файле, который содержит заголовок.

So int passed = 0; в ranker.h собирается дать вам много горя. ранг и олимпийцы оба выделили другой passed, и линкер теперь не имеет понятия, какой из них является реальным.

Так что вы, вероятно, хотите,

extern int passed; 

в ranker.h объявить, что прошло будет существовать в какой-то момент, если оно еще нет, так что не нужно выделять. Компилятор с радостью продолжит и позволит вам использовать passed.

И тогда в ranker.cpp, объявить

int passed = 0; 

passed выделить и удовлетворяют линкер. Теперь у вас есть только один passed, и любой, кто включает ranker.h, может его видеть и использовать.

Если вы хотите больше, чем один passed, вам нужно сделать что-то еще, чтобы они не обладали одинаковым именем и областью, но это не похоже на вашу цель.

Тема: противостоять желанию поставить using namespace std; в файл заголовка. Это может привести к будущим проблемам, которые могут быть очень трудно отлаживать. Подробнее здесь: Why is "using namespace std" considered bad practice?