Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95

Ошибка: "error LNK2001: неразрешенный внешний символ" при реализации шаблонного синглтона

11.04.2016, 23:36. Показов 2461. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Пытаюсь написать шаблон для синглтона, есть след. код
Сам шаблон синглтона
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
namespace BAT
{
    template<typename T>
    class _BAT_API_ ISingleton
    {
    public:
        ISingleton() {}
        static T* Instance()
        {
            if(!_instance)
                _instance = new T();
            return _instance;
        }
 
    private:
        static T* _instance;
    };
}
Его использование
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace BAT
{
    class _BAT_API_ CLogManager
    {
    public:
        CLogManager();
        void Log(string msg);
 
    private:
        std::ofstream m_LogFile;
 
    };
}
//Код ниже находится в сорс файле c реализацией CLogManager
_BAT_API_ CLogManager* ILogManager = ISingleton<CLogManager>::Instance();
Выдает след. ошибку
error LNK2001: неразрешенный внешний символ ""private: static class BAT::CLogManager * BAT::ISingleton<class BAT::CLogManager>::_instance" (?_instance@?$ISingleton@VCLogManager@BA T@@@BAT@@0PAVCLogManager@2@A)"
1>..\debug_dir\x86\bat_api_x86_d.dll : fatal error LNK1120: неразрешенных внешних элементов: 1

_BAT_API_ - макрос dllexport.
Подскажите в чем причина. Заранее благодарю.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.04.2016, 23:36
Ответы с готовыми решениями:

Error LNK2001: неразрешенный внешний символ
Помогите пожалуйста тупому нубу :) Все неприятности начались после добавления дружественного класса - class KWnd { static HWND...

Error LNK2001: неразрешенный внешний символ
Приветствую. Подскажите пожалуйста почему программа не хочет компилироваться. Имеется заголовочный файл my.h extern int foo; ...

Error LNK2001: неразрешенный внешний символ
Обязательными условиями задачи являются использование своих конструктора и деструктора. Среда программирования Visual Studio 2008. ...

13
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
11.04.2016, 23:41
Цитата Сообщение от elephants Посмотреть сообщение
одскажите в чем причина. Заранее благодарю.
Ну в классе ты статик объявил. А само место под переменную? оно за пределами класса объявляется.
Надо после тела шаблона еще добавить:
C++
1
template<typename T> T* ISingleton<T>::_instance=nullptr;
1
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
12.04.2016, 00:00
elephants,
Если у вас С++11 и не нужно управлять временем жизни, то проще и потокобезопасней вот так:
C++
1
2
3
4
5
6
7
8
9
10
template<typename T>
class _BAT_API_ ISingleton
{
public:
    static T& Instance() noexcept(T())
    {
        static T instance;
        return instance;
    }
};
1
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
12.04.2016, 01:04  [ТС]
А где в таком случае 2й раз вызывается конструктор CLogManager()? Там в реализации сообщение выводится при вызове конструктора, и выводится оно 2 раза...

Добавлено через 30 минут
Вот вся реализация класса
C++
1
2
3
4
5
6
7
8
9
10
11
12
namespace BAT
{
    CLogManager::CLogManager()
    {
        m_LogFile.open("logfile.txt");
        std::cout << "Logfile create";
    }
    void CLogManager::Log(string msg)
    {
        m_LogFile << msg << '\n';
    }
}
В тестовом проекте код
C++
1
2
3
4
5
6
int main()
{
    ILogManager.Log("Log MGR");
    std::cin.get();
    return 0;
}
Вывод будет Logfile createLogfile create

Добавлено через 3 минуты
А если перенести получение экземпляра в мэйн
C++
1
2
3
4
CLogManager& log = ISingleton<CLogManager>::Instance();
log.Log("msg");
std::cin.get();
return 0;
то конструктор вызывается один раз..
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
12.04.2016, 09:46
Цитата Сообщение от elephants Посмотреть сообщение
А где в таком случае 2й раз вызывается конструктор CLogManager()?
Насколько я понимаю, речь здесь идет о dll? Т.е. вот эта строка:
Цитата Сообщение от elephants Посмотреть сообщение
C++
1
_BAT_API_ CLogManager* ILogManager = ISingleton<CLogManager>::Instance();
находится внутри dll? Ну тогда ответ очевиден. Исполнямые модули же разные, следовательно инстанцирование шаблона (вследствие создания глобальной ссылки\указателя в цитате выше) в dll не учитывается при использовании шаблона в exe, т.е. происходит еще одно независимое инстанцирование и создание еще одного экземпляра синглтона. Боюсь, что твой код некорректен и тебе придется избавиться от шаблона вовсе, если все еще хочешь, чтобы экземпляр синглтона был действительно единственным в dll и exe. Или, как вариант, для доступа к инстансу синглтона использовать отдельную, экспортируемую функцию, которая внутри себя, в реализации dll, будет проводить инстанцирование шаблона. Впрочем, наличие шаблона все так же ставится под сомнение в этой схеме.
1
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
12.04.2016, 19:56  [ТС]
DrOffset, вообще речь идет об API игрового движка (да сложно, даже я бы сказал архи сложно для меня на данный момент.. но на ошибках учатся (не планирую писать аля cry engine..)). Задача в следующем: в апи хочу включить так сказать базу, т.е. ввод, графика, звук, логи и прочие базовые подсистемы, которые должны существовать в виде синглтона. А в последствии прикручивать к проекту самой игры данную dll-ку и оттуда вызывать методы этих объектов. И в таком случае требуется шаблон синглтона, создающий ед. экземпляр шаблонного типа. Конечно желательно этот шаблон сделать общедоступным для случаев, если, например в коде самой игры потребуется что либо в ед. экземпляре. Но базу хотелось бы заложить в dll, что бы она была определена. Вариант с отдельными синглтонами конечно проще, пока пробую через шаблоны.
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
12.04.2016, 20:08
Цитата Сообщение от elephants Посмотреть сообщение
И в таком случае требуется шаблон синглтона, создающий ед. экземпляр шаблонного типа
"Создается в единичном экземпляре" и "не может быть созданна вторая копия" это две абсолютно разных утверждения. И зачем тебе в игровом движке еще и обертки тянутых из dll функций еще в dll-b пихать? чтобы оверхед по вызову побольше был? А тем более по таким делам как опрос клавиатуры и звук. Особенно если оно под виндой. Тут по большому счету при всем богатстве выбора другой альтернативы нет. Ну с рендером там еще куда не шло кое какие варианты возможны, нр как на меня лучше все таки эти нагруженные в плане вызовов места в монолите держать.

Добавлено через 3 минуты

Не по теме:

Цитата Сообщение от elephants Посмотреть сообщение
даже я бы сказал архи сложно для меня на данный момент..
Оно всегда не так уж и просто.. и чем больше опыта в таких делах тем оно сложнее

1
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
12.04.2016, 20:13  [ТС]
Собственно, можно проблему решить создав хидер в проекте игры и написав там следующее
C++
1
CLogManager& ILogManager = ISingleton<CLogManager>::Instance();
Изначально я планировал сделать некий интерфейс в dll, но думаю того не стоит. А посредством шаблона можно любой класс, в т.ч. в проекте самой игры сделать синглтоном. Поправьте, если это ведет к проблемам))

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
лучше все таки эти нагруженные в плане вызовов места в монолите держать.
Таки лучше все убирать в сам игровой проект? Проект однозначно небольшой, практической разницы думаю особо нет в данной ситуации.. но учту на будущее.
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
12.04.2016, 20:15
Цитата Сообщение от elephants Посмотреть сообщение
Таки лучше все убирать в сам игровой проект?
Ну пока небольшой в проект. Когда разрастется можно в статическую библиотеку, чтобы код который уже не модифицируется на данном этапе глаза не мозолил.
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
12.04.2016, 20:24
Цитата Сообщение от elephants Посмотреть сообщение
Поправьте, если это ведет к проблемам))
Само по себе использование шаблона к проблемам не ведет.
В твоем случае проблемы появляются, если "пользователи" шаблона синглтона будут и со стороны dll и со стороны exe. Т.к. это два разных исполняемых модуля, функция instance вызванная и там и там, приведет к созданию двух экземпляров синглтона, что противоречит здравому смыслу. Нужно очень четко понимать что такое шаблон - это инструмент времени компиляции. Кроссмодульное связывание он обеспечить не сможет (в том смысле, что невозможно проконтролировать инстанцирование шаблона в другом исполняемом модуле).
Ты же сам убедился выше, что у тебя создается два экземпляра CLogManager. Ну какие еще вопросы могут быть? Не нужно шаманить - разберись.
0
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
12.04.2016, 20:53  [ТС]
И еще один вопрос возник... В какой момент времени будут вызываться деструкторы объектов синглтона, и будут ли они вообще вызываться (могу предположить что при завершении приложения они вызваны не будут)..
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
12.04.2016, 21:09
Цитата Сообщение от elephants Посмотреть сообщение
В какой момент времени будут вызываться деструкторы объектов синглтона, и будут ли они вообще вызываться (могу предположить что при завершении приложения они вызваны не будут)..
Если использован синглтон из 3го поста (синглтон Мейерса), то в конце работы приложения (как у глобальных переменных). Если твой первоначальный вариант, то деструктор вызван не будет. Чтобы это все-таки произошло, его необходимо доработать, например заменив указатель на smart pointer.
1
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
12.04.2016, 21:45  [ТС]
Остановлюсь пока на варианте из 3-го поста, всем спасибо за помощь.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
12.04.2016, 22:08
А у меня там ошибочка.
noexcept(T()) -> нужно заменить на noexcept(noexcept(T()))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.04.2016, 22:08
Помогаю со студенческими работами здесь

Error LNK2001: неразрешенный внешний символ
Учусь по Страуструпу, решаю задание, нужно создать header файл и два cpp и заставить работать сообща. Почему-то VS12 матерится на...

Error LNK2001: неразрешенный внешний символ
Приветствую. Пытался вшить кое-что в программу, в итоге получаю множество ошибок линковки. Вывод: Ошибка 7 error LNK1120:...

Error LNK2001: неразрешенный внешний символ
Доброго времени суток. Прочитал кучу страниц форума по поиску выданных, но так и не понял - что мне делать, имеется ошибка 1&gt;Def.obj...

Error LNK2001: неразрешенный внешний символ
Скачал библиотеку ckhttp, подключил. Когда попытался скомпилировать пример с их сайта выдало ошибки: &gt;111.obj : error LNK2001:...

Error LNK2001: неразрешенный внешний символ
имеется ошибка 1&gt; Создается библиотека .\ReleaseMinSize/AddIn.lib и объект .\ReleaseMinSize/AddIn.exp 1&gt;Command.obj : error...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru