2015-09-10 3 views
0

Я пишу пару классов для упражнений по элементам управления копированием в учебнике по программированию на C++.множественное определение: ошибка во время связи

Я поместил определения классов в соответствующие файлы заголовков и реализацию в файлах кода. Кажется, я все сделал так, как будто это должно быть сделано, но я получаю сообщение об ошибке во время соединения, которое я не могу понять (и я уже потратил полчаса, думая об этом)

вот класс сообщения (заголовки и код файлы)

message.h

#include <string> 
#include "folder.h" 

class message { 

    friend void swap(message&,message&); 

    public: 
    explicit 
    message(const std::string& =std::string()); 
    // copy control 
    message(const message&); 
    ~message(); 
    message &operator=(const message&); 
    // interface 
    void save(folder&); 
    void remove(folder&); 

    private: 
    // data members 
    std::string text; 
    std::set<folder*> folders; 
    // utility functions 
    void add_to_folders(const message&); 
    void remove_from_folders(); 

}; 

void swap(message &m1,message &m2) 
{ 
    swap(m1.text,m2.text); 
    swap(m1.folders,m2.folders); 
} 

message.cpp

#include "message.h" 

message::message(const std::string &t) : text(t) {} 

message::message(const message &other) : text(other.text),folders(other.folders) 
{ 
    add_to_folders(other); 
} 

message::~message() 
{ 
    remove_from_folders(); 
} 

message& message::operator=(const message &other) 
{ 
    remove_from_folders(); 
    text=other.text; 
    folders=other.folders; 
    add_to_folders(other); 
    return *this; 
} 

void message::save(folder &f) 
{ 
    folders.insert(&f); 
    f.addMsg(this); 
} 

void message::remove(folder &f) 
{ 
    folders.erase(&f); 
    f.remMsg(this); 
} 

void message::add_to_folders(const message& m) 
{ 
    for (auto i:m.folders) 
    i->addMsg(this); 
} 

void message::remove_from_folders() 
{ 
    for (auto i:folders) 
    i->remMsg(this); 
    folders.clear(); 
} 

и вот класс папки

folder.h

#include <set> 

class message; 

class folder { 

    public: 
    /*folder(); 
    folder(const folder&); 
    ~folder(); 
    folder &operator=(const folder&);*/ 
    void addMsg(message*); 
    void remMsg(message*); 

    private: 

    std::set<message*> messages; 

}; 

folder.cpp

#include "folder.h" 

void folder::addMsg(message *m) 
{ 
    messages.insert(m); 
} 

void folder::remMsg(message *m) 
{ 
    messages.erase(m); 
} 

Каждое сообщение содержит коллекцию указателя к папкам и наоборот. Каждый файл компилируется отлично, но когда я связываю три из них, я получаю сообщение о том, что функция swap (которую я определила в заголовке класса сообщения) переопределена.

main.cpp

#include "message.h" 

int main() 
{ 
    folder f1; 
    message m1; 
} 

Что я делаю неправильно?

+1

Пожалуйста, поставьте полный журнал ошибок компилятора/компоновщика. – anorm

ответ

2

Вы в том числе файл заголовка message.h в обоих message.cpp и main.cpp. Поскольку у вас есть:

void swap(message &m1,message &m2) 
{ 
    swap(m1.text,m2.text); 
    swap(m1.folders,m2.folders); 
} 

В message.h теперь имеют функцию подкачки объявленную как в блоке main.cpp перевода и блок message.cpp перевода. Это приведет к ошибке множественного определения. Вам необходимо переместить swap() в message.cpp

2

Помните, чтобы вы включили охранники в свои файлы заголовков?

#ifndef __MY_HEADER__ 
#define __MY_HEADER__ 

... 

#endif 

или если вы чувствуете себя комфортно, используя функции вне стандарта C++:

#pragma once 

... 
+0

Я проверил, что они не повторяются, даже если я не ставил защитников заголовка в свой код. – Luca

+0

Препроцессор определяет, что он не поможет ему в этой ситуации. –

0

Решение вашей проблемы очень просто: вы объявили void swap (data1, data2) как функцию друга в своем классе сообщений, тогда вы определяете его в нижней части вашего * .h файл. Возьмите реализацию из файла * .h и поместите ее в файл message.cpp до того, как какие-либо функции вашего класса. Убедитесь, что у вас есть определение (реализация) перед конструктором classe в файле * .cpp, так как ваш объект класса будет полагаться на эту функцию подкачки. Это должно решить вашу проблему в процессе сборки.Да, каждый из трех файлов будет скомпилирован успешно, но решение не будет создано, потому что оно не может разрешить этот метод, так как вы определили его в * .h файле. Также вы используете сообщение прототипа класса в файле folder.h, вы также должны иметь #include «message.h» в файле folder.cpp, но это потребует наличия ваших файлов * .h с #ifndef. .. #define ... директивы #endif. Это должно помочь вам!

Смежные вопросы