2016-10-03 4 views
4

Рассмотрим следующий класс:Могу ли я заставить класс наследоваться?

//! 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?

+0

Могу ли я спросить вас, почему ** вы хотите достичь этого? Если вы создаете абстрактный класс, почему бы вам это беспокоиться, если он будет создан? – Majster

+0

@majster - Хороший вопрос. Класс в моем примере технически абстрактен, но поскольку все его методы реализованы, компилятор рассматривает его как конкретный класс. Компилятор не видит, что 'm_next_value' никогда не инициализируется, что может привести к серьезным проблемам, когда счетчик не возвращает ожидаемый результат. Моя заинтересованность заключается в том, чтобы другие разработчики не могли сделать что-то глупое так: 'base_seeded_counter foo;' и иметь свой разрыв кода. –

+0

Не зависеть от производных классов от инициализации 'm_next_value'. Инициализируйте его на что-то разумное, например '0', в базовом классе и пусть производные классы сбросят его до значения по своему выбору. –

ответ

4

Учитывая, что у вас уже есть виртуальный деструктор, очевидным способом было бы объявить его чистым виртуальным. Это совершенно законно, чтобы иметь чистый виртуальный деструктор, который также определен в базовом классе:

class base_seeded_counter { 
public: 
    virtual ~base_seeded_counter() = 0; 
    int get_next(); 
protected: 
    void set_next(const int next); 
private: 
    int m_next_value; 
} 

inline virtual base_seeded_counter::~base_seeded_counter() {} 

Определения деструктора этого способ не меняет тот факт, что это чистое виртуальное, так что этот класс не может быть инстанцированным.


В качестве примечаний, которые вы в настоящее время имеете в коде, это 100% бесполезный визуальный шум. Комментарий get next о функции с именем get_next не добавляет ничего полезного.

+0

Еще одно отличное решение. Благодаря! Кстати, комментарии не такие, как в фактическом коде, я должен был просто полностью их удалить в этом примере :-) –

+0

Я выбрал это как ответ, потому что именно так я решил реализовать свое окончательное решение (у моего класса еще не было конструктор, но у него действительно был виртуальный деструктор). Оба решения абсолютно верны. –

+0

_ @ Jerry_ Бит более длинный и сложнее понять решение, чем мое. –

13

Мой вопрос: учитывая, что у меня нет чистых виртуальных методов, существует ли на C++ механизм, позволяющий кому-то создать экземпляр base_seeded_counter?

Да, дайте ему конструктор по умолчанию protected (может быть пустым).

+0

Консольные решения простых проблем делают меня все теплым и нечетким внутри. Благодаря! –

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