Рассмотрим следующий класс:Могу ли я заставить класс наследоваться?
//! Counter class base. Must be inherited.
class base_seeded_counter
{
public:
//! Destructor
virtual ~base_seeded_counter() { };
//! Get the next value.
int get_next();
protected:
//! Override the counter next value.
void set_next(const int next);
private:
int m_next_value; // Next value.
}
// ------------------------------------------------------
inline int base_seeded_counter::get_next()
{
return m_next_value++;
}
// ------------------------------------------------------
inline void base_seeded_counter::set_next(const int next)
{
m_next_value = next;
}
Целью данного класса является реализация базового счетчика объекта с намерением, что он должен быть унаследован. У него нет никаких виртуальных методов, кроме деструктора, и, что более важно, не инициализирует член m_next_value
. Это задача производного класса. Например:
class file_seeded_counter : public base_seeded_counter
{
public:
file_seeded_counter(const std::string &file_name);
void reseed();
private:
std::string m_file_name;
}
inline int file_seeded_counter::file_seeded_counter(const std::string &file_name) :
m_file_name(file_name)
{
reseed();
}
inline void file_seeded_counter::reseed()
{
int seed_from_file;
// open file here and get seed value...
set_next(seed_from_file);
}
Этот класс, извлекая из base_seeded_counter считывает начальное значение счетчика из файла, а также предлагает возможность перечитать семя из файла с помощью метода reseed()
. Могут быть и другие классы, которые предлагают аналогичную функциональность для загрузки из баз данных, сетевых источников или PRNG.
Мой вопрос заключается в следующем: учитывая, что у меня нет чистых виртуальных методов, существует ли на C++ механизм, позволяющий кому-то создать экземпляр base_seeded_counter
?
Могу ли я спросить вас, почему ** вы хотите достичь этого? Если вы создаете абстрактный класс, почему бы вам это беспокоиться, если он будет создан? – Majster
@majster - Хороший вопрос. Класс в моем примере технически абстрактен, но поскольку все его методы реализованы, компилятор рассматривает его как конкретный класс. Компилятор не видит, что 'm_next_value' никогда не инициализируется, что может привести к серьезным проблемам, когда счетчик не возвращает ожидаемый результат. Моя заинтересованность заключается в том, чтобы другие разработчики не могли сделать что-то глупое так: 'base_seeded_counter foo;' и иметь свой разрыв кода. –
Не зависеть от производных классов от инициализации 'm_next_value'. Инициализируйте его на что-то разумное, например '0', в базовом классе и пусть производные классы сбросят его до значения по своему выбору. –