Конструкторы, вызывающие подкласс

У меня есть (частично реализованная) иерархия классов, где

template<typename T> {
    class data { 
        data ( string s ) {}; // loads from file
        ...
    }
    class image: public data <T> { 
        image ( string s ) {}; // loads from file
        ...
    }
    class jpgimage : public image<T> {
        jpgimage ( string s ) {}; // loads from file 
        ...
    }
    // other image types
}

Теперь в остальной части моего кода я хотел бы иметь возможность абстрагироваться от того, является ли что-то изображением в формате JPEG или даже изображением, поэтому я хотел бы работать с data, Но в то же время я хотел бы передать этим функциям команды, специфичные для изображений JPEG.

Так что если я позвоню data<int> img("lena.jpg"); который оказывается изображением, даже изображением в формате JPEG, я хотел бы, чтобы конструктор данных вызывал конструктор изображений, который, в свою очередь, вызывает конструктор jpgimage.

Я не могу заставить его работать, и люди предупреждают о нарезке, виртуальных конструкторах и т. Д. Но так ли это странный способ настроить это?

3 ответа

Решение

Наследование должно использоваться для отношений. Итак, image<T> это data<T>, но не наоборот! Нет смысла вызывать метод, специфичный для image<T> для data<T> объект, который в конце концов не может быть image<T>, Тот факт, что вы хотите сделать это, показывает, что ваш дизайн кода имеет недостатки. Переосмыслите свой дизайн кода.

Для реализации этого вам понадобятся данные, чтобы быть владельцем реализации, а не базовый класс:

template<typename T> 
class base_data {
    base_data ( string s ) {} // loads from file
    // ...  
};

template<typename T> 
class image: public base_data <T> { 
    image ( string s ) {} // loads from file
    ... 
};

template<typename T> 
class jpgimage : public image<T> {
    jpgimage ( string s ) {} // loads from file 
    // ...
    // other image types
};

template<typename T> 
class data {
    data ( string s ) {
        if(is_jpeg( s )) impl = new jpeg_data<T>( s );
        // ...
    } // loads from file
    // ...
    private:
        base_data<T> *impl;
};

Теперь в конструкторе вы можете создать правильный тип реализации и так далее.

Я бы сказал, что это плохой дизайн. Вам не нужно работать с универсальным data классы просто для того, чтобы угадать, работаете ли вы с изображениями, если точно знаете, что делаете. Использовать image или же jpgimage класс, где вам это нужно, и заставить все остальное работать с универсальным data учебный класс.

Другие вопросы по тегам