2013-04-06 3 views
1

файлы проекта заключается в следующем:Неопределенная ссылка на (г ++ компиляции со статической библиотекой)

source 
    parser 
    parser.cpp 
    parser.hpp 
    brain 
    brain.cpp 
    brain.hpp 

Я первый побежал эти две команды (PWD source/brain/):

g++ -c brain.cpp -o brain.o 
ar rvs brain.a brain.o 

Я скопировал как brain.a и brain.hpp - source/parser/. Тогда я запустил эту команду (PWD source/parser):

g++ parser.cpp brain.a -o parser 

И я получил эту ошибку:

/tmp/cceGRLZn.o: In function `main': 
parser.cpp:(.text+0x1cc): undefined reference to `std::brain<long long>::brain()' 
parser.cpp:(.text+0x205): undefined reference to `std::brain<long long>::init(int)' 
parser.cpp:(.text+0x26b): undefined reference to `std::brain<long long>::work()' 
parser.cpp:(.text+0x2a4): undefined reference to `std::brain<long long>::clear()' 
parser.cpp:(.text+0x2ec): undefined reference to `std::brain<long long>::~brain()' 
parser.cpp:(.text+0x322): undefined reference to `std::brain<long long>::~brain()' 
/tmp/cceGRLZn.o: In function `int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)': 
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x17b): undefined reference to `std::brain<long long>::push_back(long long)' 
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x37a): undefined reference to `std::brain<long long>::push_back(long long)' 
collect2: ld returned 1 exit status 

Исходные файлы:

brain.cpp [http://ideone.com/GNUxmH][1] 
brain.hpp [http://ideone.com/M2IFAI][2] 
parser.cpp [http://ideone.com/fJRzhD][3] 
parser.hpp [http://ideone.com/mj6dST][4] 

Что я должен делать?

+0

Кажется, вы используете шаблоны через заголовок и источник, вам нужно определить эти шаблоны в заголовке и включить их. –

+0

Можете ли вы, пожалуйста, показать мне, как это первый раз, когда я использую шаблоны или, по крайней мере, обращаюсь к учебнику. –

ответ

1

Бьюсь об заклад, вы внедрили функции-члены вашего шаблона класса brain в файле .cpp. Вам необходимо предоставить определения шаблонов в файле заголовка, чтобы компилятор мог сгенерировать соответствующий код, когда он видит экземпляр шаблона. Поэтому переместите содержимое brain.cpp до brain.h.

В качестве примера, рассмотрим эти три файла:

  • test.h

    template <typename T> 
    struct test 
    { 
        void foo(T); 
    }; 
    
  • test.cpp

    #include "test.h" 
    
    template <typename T> 
    void test<T>::foo(T x) 
    { 
        // do something with x 
    } 
    
  • main.cpp

    #include "test.h" 
    
    int main() 
    { 
        test<int> t; 
        t.foo(5); 
    } 
    

Каждый .cpp собран отдельно, а затем соединены вместе. Представьте, что вы компилятор, и вы пытаетесь скомпилировать main.cpp. Вы видите, что код хочет использовать шаблон test, созданный с помощью T, как int. Итак, теперь вам нужно сгенерировать соответствующий код для test<int>::foo, но для этого вам нужно было увидеть определение функции. К сожалению, вы его не видели, поэтому вы не можете скомпилировать эту программу.

Вместо этого, определение foo должны быть перемещены в файл заголовка, чтобы привести к этому два файла программы:

  • test.h

    template <typename T> 
    struct test 
    { 
        void foo(T); 
    }; 
    
    // Alternatively, you can define this up in the class definition 
    void test<T>::foo(T x) 
    { 
        // do something with x 
    } 
    
  • main.cpp

    #include "test.h" 
    
    int main() 
    { 
        test<int> t; 
        t.foo(5); 
    } 
    

Обратите внимание, что вы не должны добавлять свои собственные декларации в std имен:

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.

3

Первое: не добавляют объект в std имен. Это дает вашу программу Неопределенное поведение.

Из вашего сообщения, похоже, вы добавили класс с именем brain в пространство имен std. Удалите brain из пространства имен std и поместите его в свое пространство имен. Единственное, что вы можете добавить в пространство имен std, это специализации шаблонов, принадлежащих к пространству имен std.

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

Отмена их в отдельном файле .cpp делает невозможным создание компилятором кода для функций-членов, которые вы вызываете из других единиц перевода, кроме тех, которые содержат их определения. This Q&A on StackOverflow также может помочь вам.

1

Вы должны объявить экземпляр мозга шаблонного класса с типом вам требуется, поэтому в brain.cpp, в конце файла, вы должны поставить:

template class brain <long long> ; 

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

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