Если я реализую метод 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();
};
В cpp ваша функция create пытается инициализировать Singleton, используя новый оператор, но вы не дадите ему конструктор. Попробуйте дать реализацию Singleton()
. то есть:
protected:
static Singleton * s_instance;
Singleton() {}
};
Вы объявили конструктор по умолчанию, и вы используете его (в new
выражении), но вы его не реализовали.
Просто удалите объявление конструктора:
protected:
static Singleton * s_instance;
// Singleton(); -- don't have this. Remove it.
};
С protected
функциями класс предназначен для наследования, так как можно гарантировать, что производный класс может быть создан только через одноэлементное оборудование?
Ну вы не имеете много контроля над производными классами, так что проще всего документально подтвердить, что каждый производный класс должен объявить и определить non- public
конструктор по умолчанию.
Тем не менее, есть трюк, который можно использовать для обеспечения этого, основываясь на том, что виртуальная база должна быть инициализирована самым производным классом. Это можно использовать, чтобы заставить клиентский код добавить окончательный вывод класса внизу. Где этот самый производный класс является экземпляром шаблона, который определяет публичный конструктор non-.
Более практичной альтернативой является перевертывание вещей в обратном порядке.
То есть вместо проектирования класса Singleton
для деривации (с сигналом защищенного материала), создайте его для наследования из класса кода клиента. Опять это означает использование шаблонов. Андрей Александреску обсудил ряд одноэлементных подходов, используя эту идею, в своей классической книге "Современный C++ дизайн".
Singleton(); // hidden constructor
Это ошибка в коде? Кроме того, он использовал static
в определении static void Singleton::Create() {...}
Почему он это делает?
protected
), доступность не наследуется, и это производный класс, который нуждается в этом применении. Т.е. это ошибка уровня дизайна. static
в порядке для Create
потому что Create
нужен только доступ к static
переменной-члену.