Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Не компилируется проект


Автор: Compositum 5.1.2013, 19:39
Доброго времени суток. Изучаю C++. 

В MS Visual Studio 2012 создал пустой C++ проект. В группу "Source Files" добавил два файла:

Файл Book.cpp:
Код

#include<cstring>

namespace ab{
    class Book{
        static int booksCount;
        char name[50];
        char author[50];
    public:
        Book(char *name, char *author);
        ~Book();
        char *GetName(){return name;}
        void SetName(const char *name){if (!*name) strcpy(this->name, name);}
        char *GetAuthor(){return author;}
        void SetAuthor(const char *author){if (!*author) strcpy(this->author, author);}
        static int GetBooksCount();
    };

    int Book::booksCount;
    int Book::GetBooksCount(){ return Book::booksCount;}

    Book::Book(char *name, char *author){
        SetName(name);
        SetAuthor(author);
        ++Book::booksCount;
    }

    Book::~Book(){
        --Book::booksCount;
    }
}

Файл main.cpp:
Код

#include<iostream>
#include"Book.cpp"

int main(){
    ab::Book book("Ivan", "Ivanov");
    ab::Book book2("Oleg", "Olegovich");
    ab::Book *p = new ab::Book("Sergey", "Sergeevich");
    std::cout << "Books count: " << ab::Book::GetBooksCount() << std::endl;
    delete p;
    std::cout << "Books count: " << ab::Book::GetBooksCount() << std::endl;
    return 0;
}


Однако скомпилировать код не удаётся:
Цитата(Текст ошибок)

Error    5    error LNK2005: "public: __thiscall ab::Book::Book(char *,char *)" (??0Book@ab@@QAE@PAD0@Z) already defined in Book.obj    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    6    error LNK2005: "public: __thiscall ab::Book::~Book(void)" (??1Book@ab@@QAE@XZ) already defined in Book.obj    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    7    error LNK2005: "public: static int __cdecl ab::Book::GetBooksCount(void)" (?GetBooksCount@Book@ab@@SAHXZ) already defined in Book.obj    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    8    error LNK2005: "private: static int ab::Book::booksCount" (?booksCount@Book@ab@@0HA) already defined in Book.obj    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    9    error LNK1169: one or more multiply defined symbols found    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\Debug\CppClasses.exe    CppClasses


Если я класс Book перепишу, сделав все функции подставляемыми (inline), то количество ошибок значительно уменьшается:

Код

#include<cstring>

namespace ab{
    class Book{
        static int booksCount;
        char name[50];
        char author[50];
    public:
        Book(char *name, char *author){
            SetName(name);
            SetAuthor(author);
            ++Book::booksCount;
        }
        ~Book(){
            --Book::booksCount;
        }
        char *GetName(){return name;}
        void SetName(const char *name){if (!*name) strcpy(this->name, name);}
        char *GetAuthor(){return author;}
        void SetAuthor(const char *author){if (!*author) strcpy(this->author, author);}
        static int GetBooksCount(){ return Book::booksCount;}
    };

    int Book::booksCount;
}


Ошибки компиляции:
Цитата

Error    5    error LNK2005: "private: static int ab::Book::booksCount" (?booksCount@Book@ab@@0HA) already defined in Book.obj    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    6    error LNK1169: one or more multiply defined symbols found    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\Debug\CppClasses.exe    1    1    CppClasses

Но Book::booksCount - это статическая переменная... Хочешь-не хочешь, а определять её вне класса придётся. Если я закомментирую определение, то вылезают ошибки:

Цитата

Error    5    error LNK2001: unresolved external symbol "private: static int ab::Book::booksCount" (?booksCount@Book@ab@@0HA)    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\main.obj    CppClasses
Error    6    error LNK1120: 1 unresolved externals    C:\Users\bushm_000\Documents\Visual Studio 2012\Projects\@Projects\Current Projects\CppClasses\Debug\CppClasses.exe    1    1    CppClasses


В чём проблема? Почему мне приходится переписывать функции как inline? Как этого избежать, если мне это не надо? И почему так и остаётся проблема со статическим полем?

Автор: feodorv 5.1.2013, 20:14
Цитата(Compositum @  5.1.2013,  20:39 Найти цитируемый пост)
В чём проблема?

Студия компилирует book.cpp в book.obj, а последний линкует с main.obj. Но в то же время Вы делаете
Цитата(Compositum @  5.1.2013,  20:39 Найти цитируемый пост)
#include"Book.cpp"

что дублирует код из book.cpp.

Переименуйте book.cpp в book.hpp или book.h...

Автор: Compositum 5.1.2013, 20:31
Цитата(feodorv @ 5.1.2013,  20:14)
Переименуйте book.cpp в book.hpp или book.h...

Переименовал и подправил include, но это не помогло :(

Добавлено через 6 минут и 48 секунд
Может это поможет - выкладываю упакованный архив с "проектом" http://tempfile.ru/file/2665099.

Автор: Compositum 5.1.2013, 21:13
Проблема решена. Если кому будет интересно поясняю: Как указывалось выше, сначала я вместо заголовочного файла через include подключил cpp файл, а этого делать нельзя... Исправляя эту ошибку, я думал, что смены расширения с cpp на h и перетаскивание мышкой файла в группу Header Files будет достаточно, но оказалось что нет... 

Сейчас сделал следующее: для файла Book.h свойству Included In Project поставил значение False - файл сразу исчез из проекта. Затем из контекстного меню добавил этот файл снова через Add Existing Item... 
После этого компиляция прошла успешно.

Теперь всё заработало.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)