C ++:对象错误的多重定义

时间:2017-05-14 19:56:47

标签: c++ makefile include

我最近开始使用C ++进行文件结构化,但收效甚微。该项目分为以下文件

-groups.h
   -groups.cpp 
-people.h    
   -people.cpp
-main.cpp

有两个基类,groupsplayers以及其中任何一个继承的其他类。

这是文件

groups.h

#ifndef GROUPS_H
#define GROUPS_H


//Groups of people one of the base classes
class groups {
    int num_of_people;
    float avg_age;
    friend class SoccerTeams;
public:
    //virtual string getclass() { return char2str(typeid(*(this)).name()); }
    groups(int numb = 0): num_of_people(numb) {};
    ~groups(){};
};

//SoccerTeam group class
class SoccerTeams : public groups {
    std::string teamName;
    std::vector<SoccerTeams> teams;
    int teamId;
public:
    Players player;
    void addManager();
    std::string nameTeam(int);
    void deletePlayer(int);
    void showTeam();
    void addPlayer();
    void showPlayers();
    void showManagers();
    void exportToFile(const char *);

    SoccerTeams() {};
    SoccerTeams(std::string, int);
    ~SoccerTeams() {};
};

//FanClub group class
class FanClubs : public groups{
    std::string clubName; 
    int clubId;
    std::vector<FanClubs> fanclubs;
public:
    Fans fan;
    void addFans();
    void showFans();
    FanClubs() {};
    FanClubs(std::string, int);
    ~FanClubs() {};
};

#endif

groups.cpp

#include <algorithm>
#include <iostream>
#include <vector>
#include <typeinfo>
#include <boost/units/detail/utility.hpp>
#include <cstdlib>
#include <fstream>
#include <list>
#include "groups.h"

using namespace std;

//Fan Club member functions 
FanClubs::FanClubs(string name, int id) {
    clubName = name;
    clubId = id;
    fanclubs.push_back(*this);
};

void FanClubs::showFans() {
    cout << "Players in " << fanclubs.begin() -> clubName << endl;
    fan.showFanas();
}

void FanClubs::addFans() {
    int choice = 0;
    cout << "1. Add a bunch of fans\n2. Add custom fans\nChoice: ";
    cin >> choice;
    switch(choice) {
        case 1: {
            int requirement;
            cout << "How many fans do you need: ";
            cin >> requirement;
            static const string names[] = {
                "Margarita", "Amalia", "Sam", "Mertie", "Jamila", "Vilma", 
                "Mazie", "Margart", "Lindsay", "Kerstin", "Lula", "Corinna", "Jina",
                "Jimmy", "Melynda", "Demetrius", "Beverly", "Olevia", "Jessika", 
                "Karina", "Abdallah", "Max", "Prateek", "Aghaid"
            };
            for (int i = 0; i < requirement; ++i) {
                fan.name = names[rand() % 24];
                fan.age = (rand() % 80 + 1);
                fan.sex = ((rand() % 2) ? 'M' : 'F');
                fan.under_auth = false;
                fan.auth_level = 0;
                fans.push_back(fan);
            }
            break;   
        }           
        case 2: {
            int requirement;
            cout << "How many fans you want to add?\nnumber: ";
            cin >> requirement;
            for (int i = 0; i < requirement; ++i) {
                cout << "======Fan " << i + 1 << "=======\n";
                cout << "Enter name: ";
                cin >> fan.name;
                cout << "Enter age: ";
                cin >> fan.age;
                cout << "Enter sex: ";
                cin >> fan.sex;
                fan.under_auth = false;
                fan.auth_level = 0;
                fans.push_back(fan);
            }   
            break;
        }
        default: 
        cout << "Incorrect choice\n";
        break;
    }
}

//Soccer Teams member functions 
string SoccerTeams::nameTeam(int id) {
    return teams.begin() -> teamName;
}

void SoccerTeams::showPlayers() {
    cout << "Players in " << teams.begin() -> teamName << endl;
    player.showPlayas();
}

void SoccerTeams::showManagers() {
    int counter = 1;
    list<ManagingDirectors>::iterator i;
    for (i = directors.begin(); i != directors.end(); i++) {
        cout << "Director " << counter << endl;
        cout << "Works for team " << nameTeam(i -> directorId) << endl;
        cout << "Name: " << i -> name << endl;
        cout << "Sex: " << i -> sex << endl;
        counter++;
    }
}

void SoccerTeams::addPlayer() {
    int newId;
    int number;
    cout << "Number of players to be added: ";
    cin >> number;
    for (int i = 0; i < number; ++i) {
        cout << "\nEnter player name: ";
        cin >> player.name;
        cout << "Enter sex(M/F): ";
        cin >> player.sex;
        cout << "Enter age: ";
        cin >> player.age;
        cout << "Enter player id(0 for random id): ";
        cin >> newId;
        newId == 0 ? player.playerId = (rand() % 100 + 1) : player.playerId = newId;
        player.under_auth = true;
        player.auth_level = 0;
        players.push_back(player);
        teams.begin()->num_of_people++;
    }
}

void SoccerTeams::deletePlayer(int id) {
    std::vector<Players>::iterator i;
    for (i = players.begin(); i != players.end(); ) {
        if(i->playerId == id) {
            i = players.erase(i);
            teams.begin()->num_of_people--;
        }
        else
            i++;
    }
}

void SoccerTeams::showTeam() {
    vector<SoccerTeams>::iterator i;
    for (i = teams.begin(); i != teams.end(); ++i) {
        cout << "\nTeam name: " << i -> teamName << endl;
        cout << "Team id: " << i -> teamId << endl;
        cout << "Number of players: " << i -> num_of_people << endl;
        cout << "Average age: " << i -> player.ageCalc()/teams.begin() -> num_of_people << endl;
    }
}

SoccerTeams::SoccerTeams(string tn, int id) {
    teamName = tn;
    teamId = id;
    teams.push_back(*this);
};

void SoccerTeams::addManager() {
    ManagingDirectors mandir;
    int number;
    cout << "How many managers you want to add: ";
    cin >> number;
    for (int i = 0; i < number; i++) { 
        cout << "Manager " << i + 1 << endl;
        cout << "Enter name of the director: ";
        cin >> mandir.name;
        cout << "Enter the age: ";
        cin >> mandir.age;
        cout << "Enter the sex(M/F): ";
        cin >> mandir.sex;
        mandir.directorId = teams.begin() -> teamId;
        mandir.auth_level = 3;
        mandir.under_auth = false;
        directors.push_front(mandir);
    }
}

void SoccerTeams::exportToFile(const char *filename) {
    ofstream outfile;
    outfile.open(filename, ios::out);
    vector<Players>::iterator i;
    int counter = 1;
    outfile << "Team Data" << endl;
    outfile << "Team name  : " << teamName << "\nPlayers    : " << teams.begin() -> num_of_people << endl;
    outfile << "Average age: " << teams.begin() -> player.ageCalc()/teams.begin() -> num_of_people << endl;
    for (i = players.begin(); i != players.end(); ++i) {
        outfile << "\nPlayer " << counter << endl;
        outfile << "Name: " << i -> name << endl;
        outfile << "Sex : " << i -> sex << endl;
        outfile << "Age : " << i -> age << endl;
        outfile << "Pid : " << i -> playerId << endl;
        counter++;
    }

    outfile.close();
}

people.h

#ifndef PEOPLE_H
#define PEOPLE_H

//People base class
class people {
    string name;
    char sex;
    int age;
    bool under_auth;
    int auth_level;
    friend class SoccerTeams;
    friend class Players;
    friend class Fans;
    friend class FanClubs;
public:
    //virtual string getclass() { return char2str(typeid(*(this)).name()); }
    people(){};
    ~people(){};    
    //virtual int get_age(){ return this->age; }; 
};

//players class people
class Players : public people {
    int playerId;
    int avgAge;
    friend class SoccerTeams;
public:
    void showPlayas();
    float ageCalc();
    Players(){};
    ~Players(){};
};
std::vector<Players> players;

//Class Managing Directors people 
class ManagingDirectors : public people {
    int directorId;
    friend class SoccerTeams;
public:
    ManagingDirectors(int);
    ManagingDirectors() {};
    ~ManagingDirectors(){};
};
std::list<ManagingDirectors> directors;


//Fans people class
class Fans : public people {
public:
    void showFanas();
    Fans(){};
    ~Fans(){};
};
std::vector<Fans> fans;

#endif

people.cpp

#include <algorithm>
#include <iostream>
#include <vector>
#include <typeinfo>
#include <boost/units/detail/utility.hpp>
#include <cstdlib>
#include <fstream>
#include <list>
#include "people.h"

using namespace std;
const int vector_resizer = 50;
string char2str(const char* str) { return boost::units::detail::demangle(str); }


//Fan class member functions
void Fans::showFanas() {
    int counter = 1;
    vector<Fans>::iterator i;
    for (i = fans.begin(); i != fans.end(); ++i) {
        cout << "\nFan " << counter << endl;
        cout << "Name: " << i -> name << endl;
        cout << "Sex: " << i -> sex << endl;
        cout << "Age: " << i -> age << endl;
        counter++;
    }
}


//Players class member functions
float Players::ageCalc() {
    int totalAge = 0;
    vector<Players>::iterator i;
    for (i = players.begin(); i != players.end(); ++i) {
        totalAge += i->age;
    }
    return totalAge;
}

void Players::showPlayas() {
    int counter = 1;
    vector<Players>::iterator i;
    for (i = players.begin(); i != players.end(); ++i) {
        cout << "\nPlayer " << counter << endl;
        cout << "Name: " << i -> name << endl;
        cout << "Sex: " << i -> sex << endl;
        cout << "Age: " << i -> age << endl;
        cout << "Player id: " << i -> playerId << endl;
        counter++;
    }
}

//Member functions of Managing DIrectos
ManagingDirectors::ManagingDirectors(int number) {
    directorId = number;
};

除了这些文件,我还有一个makefile。

//makefile

footballmaker: main.o groups.o people.o  
    gcc -o main main.o groups.o people.o 
    rm groups.o people.o  

同样here's一个文件中的所有代码,它现在的工作方式。

当我尝试制作程序时,我收到以下错误,

gcc -o main main.o groups.o people.o 
groups.o:(.bss+0x0): multiple definition of `players'
main.o:(.bss+0x0): first defined here
groups.o:(.bss+0x20): multiple definition of `directors[abi:cxx11]'
main.o:(.bss+0x20): first defined here
groups.o:(.bss+0x40): multiple definition of `fans'
main.o:(.bss+0x40): first defined here
people.o:(.bss+0x0): multiple definition of `players'
main.o:(.bss+0x0): first defined here
people.o:(.bss+0x20): multiple definition of `directors[abi:cxx11]'
main.o:(.bss+0x20): first defined here
people.o:(.bss+0x40): multiple definition of `fans'
main.o:(.bss+0x40): first defined here

...

collect2: error: ld returned 1 exit status
makefile:3: recipe for target 'footballmaker' failed
make: *** [footballmaker] Error 1

整个错误超过400行,附加here

我不确定如何包含文件,因此我不会复制它们,因为需要文件才能使程序正常工作,是否有更好的方法将我的代码拆分成文件?

1 个答案:

答案 0 :(得分:0)

您在头文件people.h中的文件范围定义(而不仅仅是声明!)变量。在链接时,所有其他翻译单元都可以看到这样的变量定义。如果不同的翻译单元,例如people.cppmain.cpp,现在包含people.h,这就好像这些变量定义已直接写入people.cppmain.cpp,每次定义一个在全局范围内使用相同名称的单独变量。

为了解决这个问题,声明头文件中的变量,但仅在一个翻译单元中定义,例如people.cpp。只是声明一个变量意味着将关键字extern放在它前面(告诉编译器在链接时由不同的翻译单元提供变量定义):

// people.h
extern std::vector<Players> players;
extern std::list<ManagingDirectors> directors;
extern std::vector<Fans> fans;

// people.cpp
std::vector<Players> players;
std::list<ManagingDirectors> directors;
std::vector<Fans> fans;