Ошибка связи c ++, если функция реализована в .cpp

0

Если я реализую метод create класса в.cpp, я получаю

ошибка LNK2019: неразрешенный внешний символ "protected: __thiscall Singleton :: Singleton (void)" (?? 0Singleton @@IAE @XZ), на который ссылается функция "public: static void __cdecl Singleton :: create (void)" (? create @Singleton @@SAXXZ

Однако, если я реализую метод внутри файла заголовка, он компилируется без ошибок: S

файл заголовка

 #pragma once
 #include <iostream>
class Singleton
{
 public:

static Singleton * getInstance()
{
    return s_instance;
}

static void create();
static void destroy();

void help();

protected:

static Singleton * s_instance;
Singleton();
};

исходный файл:

#include "Singleton.h"

Singleton * Singleton::s_instance = NULL;

 void Singleton::create()
{
    if (!s_instance)
    {
         s_instance = new Singleton;
    }
}



void Singleton::destroy()
{
    delete s_instance;
    s_instance = NULL;
}

Однако, если я реализую метод create внутри заголовка, он не вызывает ошибок

Файл заголовка с внедренным в него методом create

#pragma once
#include <iostream>
class Singleton
{
public:

    static Singleton * getInstance()
    {
        return s_instance;
    }

    static void create(){
        if (!s_instance)
        {
            s_instance = new Singleton;
        }
    }
    static void destroy();


protected:

    static Singleton * s_instance;
    Singleton();
};
Теги:
static
singleton
linker-errors

2 ответа

3
Лучший ответ

В cpp ваша функция create пытается инициализировать Singleton, используя новый оператор, но вы не дадите ему конструктор. Попробуйте дать реализацию Singleton(). то есть:

protected:

    static Singleton * s_instance;
    Singleton() {}
};
  • 0
    Ба. Ты подтолкнул меня на это.
  • 0
    Я хотел бы принять ответы менее чем за 3 минуты
Показать ещё 5 комментариев
0

Проблема.

Вы объявили конструктор по умолчанию, и вы используете его (в new выражении), но вы его не реализовали.

Фикс.

Просто удалите объявление конструктора:

protected:

    static Singleton * s_instance;
    // Singleton();  -- don't have this. Remove it.
};

Другие вопросы.

С protected функциями класс предназначен для наследования, так как можно гарантировать, что производный класс может быть создан только через одноэлементное оборудование?

Ну вы не имеете много контроля над производными классами, так что проще всего документально подтвердить, что каждый производный класс должен объявить и определить non- public конструктор по умолчанию.

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

Более практичной альтернативой является перевертывание вещей в обратном порядке.

То есть вместо проектирования класса Singleton для деривации (с сигналом защищенного материала), создайте его для наследования из класса кода клиента. Опять это означает использование шаблонов. Андрей Александреску обсудил ряд одноэлементных подходов, используя эту идею, в своей классической книге "Современный C++ дизайн".

  • 0
    Я полагаю, что ОП берет этот код из этой книги amazon.com/For-Game-Programmers-Development-Series/dp/… и у меня та же проблема. Внутри класса есть Singleton(); // hidden constructor Это ошибка в коде? Кроме того, он использовал static в определении static void Singleton::Create() {...} Почему он это делает?
  • 1
    @CroCo: это попытка обеспечить, чтобы никакие другие экземпляры не могли быть созданы. Но он ошибочен, он не может работать, потому что он спроектирован как базовый класс (обозначен как protected ), доступность не наследуется, и это производный класс, который нуждается в этом применении. Т.е. это ошибка уровня дизайна. static в порядке для Create потому что Create нужен только доступ к static переменной-члену.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню