Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 4.75
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

Проблема с линковкой - C++

15.10.2011, 16:20. Просмотров 1090. Ответов 6
Метки нет (Все метки)

До сих пор мучаю злосчастный класс (в далёком прошлом это был класс студенты), пытаясь разнести всё по файлам получаю проблемы с линковкой.
Собственно описание проблемы:
есть main файл (ничего не делает, только подключает .h файл списка)
C++
1
2
3
4
5
6
7
#include <iostream>
#include "List.h" // ОСНОВНОЕ НАЗНАЧЕНИЕ MAIN
 
int main()
{
    return 0;
}
Есть класс-элемент списка (по совместительству просто данные о студентах, ничего сложного, класс работает если подключить ТОЛЬКО ЕГО в main (и в проекте если нет List.h)):
CStudent.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef CSTUDENT_H
#define CSTUDENT_H
 
#include <iostream>
using std::ostream;
using std::istream;
 
#include <iomanip>
using std::setw;
using std::left;
 
#include <string>
using std::string;
 
class CStudent
{
    friend ostream &operator<<(ostream& os,const CStudent& stud);
    friend istream &operator>>(istream& is,CStudent& stud);
    void swap(CStudent &_v);
 
    //сравнивание на основании фамилии (sname)
    int cmp(const CStudent&, const CStudent&) const;
 
 
    string fname;
    string sname;
    string tname;
    string group;
    int year;
    float average;
 
 
public:
    CStudent(string ="",string ="",string ="",string ="",int =0,float =0);
    CStudent& operator=(const CStudent &_v);
 
    void setFname(string s){fname=s;}
    string getFname() const{return fname;}
    void setSname(string s){sname=s;}
    string getSname() const {return sname;}
    void setTname(string s){tname=s;}
    string getTname() const{return tname;}
    void setGroup(string g){group=g;}
    string getGroup() const{return group;}
    void setYear(int y){year=(y>=1950 && y<=2012 ? y : -1);}
    int getYear() const{return year;}
    void setAverage(float aver){average=(aver>=0 && aver<=100 ? aver : -1);}
    float getAverage() const{return average;}
 
 
    bool operator==(const CStudent &right) const;
    bool operator!=(const CStudent &right) const;
    bool operator>(const CStudent &right) const;
    bool operator>=(const CStudent &right) const;
    bool operator<(const CStudent &right) const;
    bool operator<=(const CStudent &right) const;
};
 
 
 
 
 
 
CStudent::CStudent(string f,string s,string t,string gr,int y,float aver)
:fname(f),sname(s), tname(t),group(gr)
{
    setAverage(aver);
    setYear(y);
}
 
void CStudent::swap(CStudent &_v)
{
    std::swap(fname,_v.fname);
    std::swap(sname,_v.sname);
    std::swap(tname,_v.tname);
    std::swap (group,_v.group);
    std::swap(year,_v.year);
    std::swap(average,_v.average);
}
 
int CStudent::cmp(const CStudent &s1, const CStudent &s2) const
{
    return (s1.fname.compare(s2.fname));
}
 
 
 
///////////////////////operator's/////////////////////////
 
CStudent& CStudent::operator=(const CStudent &_v)
{
    if(this != &_v)
     CStudent(_v).swap(*this);
    return *this;
}
 
bool CStudent::operator==(const CStudent &right) const
{
    return (cmp(*this,right)==0);
 
}
 
bool CStudent::operator!=(const CStudent &right) const
{
    return (cmp(*this,right)!=0);
 
}
 
bool CStudent::operator>(const CStudent &right) const
{
    return (cmp(*this,right)>0);
}
 
bool CStudent::operator>=(const CStudent &right) const
{
    return (cmp(*this,right)>=0);
}
 
bool CStudent::operator<(const CStudent &right) const
{
    return (cmp(*this,right)<0);
}
 
bool CStudent::operator<=(const CStudent &right) const
{
    return (cmp(*this,right)<=0);
}
 
ostream& operator<<(ostream& os,const CStudent& stud)
{
    os<<setw(8)<<left<<stud.fname
     <<setw(10)<<left<<stud.sname
     <<setw(12)<<left<<stud.tname
     <<setw(7)<<stud.group
     <<setw(5)<<stud.year
     <<setw(7)<<stud.average<<"\n";
 
     return os;
}
 
istream &operator>>(istream& is,CStudent& stud)
{
    is>>stud.fname>>stud.sname>>stud.tname
     >>stud.group>>stud.year>>stud.average;
    return is;
}
 
#endif


И есть класс-список, элементами которого является структура ListItem содержащая студентов
List.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef LIST_H
#define LIST_H
 
#include "CStudent.h"
//#include "ListIterator.h"
 
class List
{
    struct ListItem
    {
        CStudent data;
        ListItem *Next;
        ListItem(const CStudent& first,ListItem *next=0){data=first;Next=next;};
    };
 
    ListItem *Head;
    ListItem *Tail;
 
public:
    //friend class ListIterator<ListItem, CStudent>;
 
    List(): Head(0), Tail(0){}
    List(const CStudent& stud);
    ~List(){this->deleteAll();}
 
 
    void addToTail(const CStudent&);
    void addToHead(const CStudent&);
 
 
    bool deleteFromHead();
    bool deleteFromTail();
    void deleteAll();
 
    //void sort();
    //ListIterator<ListItem,CStudent> findElement(CStudent &what); //поиск по всему списку
    //ListIterator<ListItem,CStudent> findElement(CStudent &what, ListIterator<ListItem,CStudent> begin, ListIterator<ListItem,CStudent> end);//поиск с границами
    //bool findAndDestroy(const CStudent& stud);
 
 
    //ListIterator<ListItem,CStudent> begin()const {return ListIterator<ListItem,CStudent>(Head);}
    //ListIterator<ListItem,CStudent> end() const {return ListIterator<ListItem,CStudent>(0);}
};
 
 
#endif


List.cpp

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include "List.h"
 
List::List(const CStudent& stud)
{
    Head=Tail=new ListItem(stud, 0);
}
 
void List::addToTail(const CStudent& right)
{
    if (Tail)
    {
        Tail->Next=new ListItem(right,0);
        Tail=Tail->Next;
    }
    else
     Head=Tail=new ListItem(right,0);
}
 
 
void List::addToHead(const CStudent& right)
{
    if (Head)
    {
        ListItem* temp=Head;
        Head=new ListItem(right,temp);
        Head->Next=temp;
    }
    else
        Head=Tail=new ListItem(right,0);
}
 
bool List::deleteFromHead()
{
    if(!Head) //удалять нечего
     return false;
 
    else if(!(Head->Next))//только один элемент
    {
        delete Head;
        Head=Tail=NULL;
        return true;
    }
 
    ListItem *temp=Head;
    Head=Head->Next;
    delete temp;
    return true;
}
 
bool List::deleteFromTail()
{
    if(!Tail)//удалять нечего
     return false;
 
    else if(Tail==Head)//только один элемент
    {
        delete Tail;
        Head=Tail=NULL;
        return true;
    }
    ListItem *temp=Head;
    while(temp->Next!=Tail)//найти новый хвост
     temp=temp->Next;
 
    ListItem *toDelete=Tail;
    Tail=temp;
    temp->Next=0;
    delete toDelete;
    return true;
}
 
 
void List::deleteAll() // освободить память
{
    ListItem* temp;
    while(Head)
    {
        temp=Head;
        Head=Head->Next;
        delete temp;
    }
    Tail=Head; //Head=NULL
}
 
//void List:: sort()
//{
//    ListItem* new_begin=NULL;
//    ListItem* new_end=NULL;
//    ListItem* sprev=NULL;
//
//    for(ListItem *scur=this->Head;scur!=NULL;scur=this->Head)
//    {
//        ListItem *smin=NULL;
//        ListItem *sminprev=scur;
//        CStudent min_elem=scur->data;
//        for(ListItem *gp=scur->Next;gp!=NULL;gp=gp->Next)
//        {
//            if((gp->data)<=min_elem)
//            {
//                min_elem=gp->data;
//                smin=gp;
//                sprev=sminprev;
//            }
//            sminprev=gp;
//        }
//        if(smin==NULL)
//        {
//            smin=scur;
//        }
//        else if(smin==scur->Next)
//        {
//            scur->Next=scur->Next->Next;
//        }
//        else
//        {
//            sprev->Next=smin->Next;
//        }
//        if(new_begin!=NULL)
//        {
//            new_end->Next=smin;
//            new_end=smin;
//        }
//        else
//        {
//            new_begin=smin;
//            new_end=smin;
//        }
//        if(smin==this->Head)
//         this->Head=smin->Next;
//    }
//    this->Head=new_begin;
//    this->Tail=new_end;
//
//}
 
//bool List::findAndDestroy(const CStudent& stud)
//{
//    if(!Head)
//     return false;
//
//    ListItem *temp=Head;
//    if(temp->data==stud) //если это первый элемент
//    {
//        this->deleteFromHead();
//        return true;
//    }
//    ListItem* beforeTemp=temp;
//    temp=temp->Next;
//
//    while(temp)
//    {
//        if((temp->data==stud))
//        {
//             beforeTemp->Next=temp->Next;
//             delete temp;
//             return true;
//        }
//
//        beforeTemp=temp;
//        temp=temp->Next;
//    }
//
//    return false;//такого элемента нет в списке
//}
 
//ListIterator<ListItem,CStudent> List::findElement(CStudent &what, ListIterator<ListItem,CStudent> begin, ListIterator<ListItem,CStudent> end)
//{
//    for(;begin!=end;++begin)
//    {
//        if ((*begin)==what)
//         return begin;
//    }
//    //если ничего не найдено - вернуть итератор указывающий за конец списка (на NULL)
//    return ListIterator<ListItem,CStudent>(NULL);
//}
 
//ListIterator<ListItem,CStudent> List::findElement(CStudent &what)
//{
//    return (this->findElement(what,this->begin(),this->end()));
//}


Проблема в том что если подключаю свой List.h то линковщик тут же бесится и ругается что все методы класса CStudent уже определены и я мол в классе CStudent.h внизу пытаюсь их переопределить что делать нельзя.

minigw ругается
так
Код
obj\Debug\List.o(.text+0x100)||In function `ZN8CStudentC2ESsSsSsSsif':|
C:\C++\Projects\StudentsVer3\CStudent.h|65|multiple definition of `CStudent::CStudent(std::string, std::string, std::string, std::string, int, float)'|
obj\Debug\main.o(.text+0x100):C:\C++\Projects\StudentsVer3\CStudent.h|65|first defined here|
obj\Debug\List.o(.text+0x26c)||In function `ZN8CStudentC1ESsSsSsSsif':|

...

||=== Build finished: 26 errors, 0 warnings ===|


VS 6.0:
так
Код
List.obj : error LNK2005: "public: __thiscall CStudent::CStudent(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class st


Всё это работало раньше, а вот когда надумал немного переразнести по разным файлам получилась такая странная проблема, которую я не знаю как решить и из-за чего она возникает, вроде-бы всё как и надо в ifndef - endif заключил ... не понятно мне в чём проблема. Подскажите пожалуйста что же не так, на всякий случай оставляю в прикреп. файле все выше перечисленные файлы.
Вложения
Тип файла: zip List.zip (2.9 Кб, 13 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.10.2011, 16:20     Проблема с линковкой
Посмотрите здесь:

Проблема с линковкой - C++
Пишу игру в Code::Blocks, использую glut. Компилятор ошибок не выдаёт и обьектные файлы создаются, а вот линковщик ругается: ...

проблемы с линковкой - C++
Возникла проблема. Нашел на другом форуме точную формулировку своей проблемы. Решение той проблемы не описано. Прошу помочь:

Дорогие, помогите с линковкой libeay32.lib - C++
Здравствуйте, Уважаемые гуру! Собираю ntp-сервер, написанный на &quot;с&quot;. Называется ntp 4.2.6p3...

В чём разница между динамической и статической линковкой библиотеки? - C++
В чём разница между динамической и статической линковкой библиотеки? Если можно с примером.

Проблемы с линковкой к библиотекам при установке LLVM Clang (не находит заголовочные файлы) - C++
Скачал и установил пакет LLVM-3.7.0 на Windows 7. Но при попытке скомпилировать файл 01.cpp с помощью команды clang++.exe 01.cpp, получил...

Проблeма с линковкой - Assembler
Здравствуй, подскажите пожалуйста, в чём причина ошибок, я сперва компилирую, а затем линкую программу, на этапе линковки возникают ошибки,...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
aeshes
440 / 203 / 13
Регистрация: 07.10.2011
Сообщений: 462
15.10.2011, 16:42     Проблема с линковкой #2
Gepar, а есть какая-то причина оставить реализацию студентов в h-файле, а не в cpp?
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
15.10.2011, 16:54  [ТС]     Проблема с линковкой #3
aeshes, разбил ещё и на cpp файл - помогло, но почему? В чём была проблема тогда?
aeshes
440 / 203 / 13
Регистрация: 07.10.2011
Сообщений: 462
15.10.2011, 16:58     Проблема с линковкой #4
Gepar, честно сказать даже не знаю( просто помню, что нужно делать так, а вот почему? увы...
Gepar
1175 / 531 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
15.10.2011, 17:11  [ТС]     Проблема с линковкой #5
aeshes, ладно, тогда тоже постараюсь запомнить (как например то что при перегрузке оператора << второй аргумент должен быть const), и всё же мне не понятно: ведь без файла в проэкте List.h всё хорошо компилируется да и так по стандарту всё ок: объявление,а потом внизу указывая определение к какому классу относится идёт определение, я до этого думал что компилятору пофиг на разрешения файла и он обращается одинаково как с .h так и с .cpp файлами, а оно оказывается не так.
TheAthlete
152 / 152 / 13
Регистрация: 31.08.2010
Сообщений: 535
15.10.2011, 20:40     Проблема с линковкой #6
Компилято и будет ругаться. Суть вот в чем:
Программы, состоящие из нескольких файлов, нуждаются в способе связи используемых имен и объявлений. В языке С++ для этого используются файлы заголовка (.h).

Для обеспечения возможности разделить программу на несколько частей, язык С++ предоставляет технологию, известную как раздельная компиляция (separate compilation). Раздельная компиляция позволяет составлять программу из нескольких файлов.

Поэтому объявление класса нужно писать в файле .h и обрамлять следующими макросами
#ifndef CSTUDENT_H
#define CSTUDENT_H

#endif

Этот блок нужен, чтобы повторно не влючать заголовок во многих файлах. Скорее всего компилятор на это и ругается. Сообщение компилятора "multiple definition of" явное тому доказательство.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.10.2011, 20:47     Проблема с линковкой
Еще ссылки по теме:

Проблемы с линковкой - C++
Возникла проблема. Нашел на другом форуме точную формулировку своей проблемы. Решение той проблемы не описано. Прошу помочь: ...

Запуск приложения с линковкой с определёнными библиотеками - Linux
Возможно ли запустить бинарник на выполнение так чтобы он при запуске линковался не с теми so-шками, которые лежат, например в /lib а с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
15.10.2011, 20:47     Проблема с линковкой #7
Gepar, у вас два разных .cpp файла List.cpp и видимо main.cpp включают файл Student.h
получается что в обоих класса есть определение методов студента
это пресекается линковщиком
Yandex
Объявления
15.10.2011, 20:47     Проблема с линковкой
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru