2011-01-03 4 views
1


У меня есть класс шаблона, который открывается, в котором я добавил метод. Этот класс находится в пространстве имен A. Теперь я вызываю этот метод в другое пространство имен (скажем, B). Первоначально компилятор дал мне ошибку компоновщика, в которой говорилось «неразрешенный внешний символ» для этого конкретного метода.
Однако, если я вызываю этот метод внутри одного и того же пространства имен (это A), он хорошо связывается. После этого он хорошо связывается и в пространстве имен B.
Почему это могло произойти?
Связано ли это с созданием объекта Template моего класса?
Атула
Вот фрагмент кода ...Шаблон класса, дающий ссылку на ошибку

namespace sss 
{ 
    namespace AAA 
    { 
     template <<typename T, typename TAlloc = Allocator<T> > 
     class DLL_EXPORT A 
     { 
      public: 
      // Some other functions that are working fine ... 
      bool fooA() const; 
      { 
        return Size()>0; 
      } 
     }; 
    } 
} 


//I get a linker error when I call it in another namespace (say B)... 
//I am accessing this method in public method of some other class in namespace B 

// Including the header for class A ... 
#include A.h 

namespace QQQ 
{ 
    namespace B 
    { 
     class B 
     { 
      private: 
      AAA::A obj; // Object of class A ... 
      public: 
      // SOme methods 
      // Method that calls fooA ... 
      GetResult() 
      { 
       fooA // This causes causes linker error when i call it here, 
        // but, it works when i call it in namespace AAA, 
        // and then it, it works here as well 
      } 
     }; 

Когда я называю этот метод из пространства имен B, это дает неразрешенный внешний символ, но, когда я называю это внутри пространства имен A, он связывает хорошо в A, и снова в B.
Любые идеи?

+0

Можете ли вы привести пример минимального кода, который демонстрирует это? –

+0

Можете ли вы показать свой код? – UmmaGumma

+2

Мне просто интересно, что означает templaet namespace? – UmmaGumma

ответ

0

Неправильно используется шаблонный класс. Следующие должны работать:

namespace QQQ 
{ 
    namespace B 
    { 
     class B 
     { 
      // Note the template parameter (int) 
      AAA::A<int> obj; 

      public: 
      bool GetResult() const 
      { 
       // Note the parentheses and the "obj" 
       return obj.fooA() 
      } 
     }; 
    } 
} 

Единственная проблема, которую я могу себе представить, с этим кодом будет неоднозначность между B имен и B класса, но полностью квалифицированное вызов (QQQ::B::B) должен работать.


По вашему симптому (ошибка линкера при вызове из пространства имен, кроме A, но без каких-либо ошибок компоновщика, если также вызывается из имен A), а затем - при условии, что ваш синтаксис является правильным в Вашем коде - ваш проблема в том, что вы неправильно создаете шаблон. Шаблоны - это конструкции времени компиляции, и поэтому они действительно не могут быть скомпилированы в библиотеки DLL. Вместо этого шаблон должен быть правильно создан во время компиляции. Когда вы не получаете ссылки на ошибки, это потому, что шаблон правильно создан, и когда вы получаете ссылку на ошибки, это происходит потому, что этого не было.

Из-за символа DLL_EXPORT Я предполагаю, что вы используете Visual C++. Несмотря на это, у реселлеров GCC есть good write-up, который также относится к Visual Studio. Большинство шаблонных библиотек, с которыми я знаком (например, Boost), требуют, чтобы все шаблоны были объявлены и определены в файле заголовка. Также законно явно создавать шаблоны, как рекомендовано ребятами GCC.

0

У меня была такая же проблема с Borland 5 Professional. Я получил ошибку компоновщика с внешним справочным сообщением. Решение состояло в том, чтобы включить .cpp-файл в конец вашего заголовка. Поскольку компилятор должен иметь полное определение, чтобы иметь возможность создавать экземпляр шаблона. Поэтому он должен быть определен в блоке перевода, в котором вы хотите его использовать.

Надеюсь, что это поможет.

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