Почему не хорошо производить от контейнеров стандарт?

Вопрос появляется из этого ответа.

Не хорошо происходить от классов, которые не были сделаны для того, чтобы он произошел от них (контейнеры стандарт). Мог бы быть использованным состав, хотя я сейчас не вижу преимущество.

Это так?

Какие недостатки имеет производить от контейнера стандарт как, например, std:: set?

Почему предпочтительный состав?

5
задан 13.04.2017, 16:00
1 ответ

Не хорошо происходить от классов, которые не были сделаны для того, чтобы он произошел от них (контейнеры стандарт). Мог бы быть использованным состав, хотя я сейчас не вижу преимущество.

Это так?

Он это. Ответ asdasdasd делает ясное упоминание, которое не должно не производить от контейнеров стандарт, но может быть экстраполированным в любой другой объект будьте контейнером или нет, будьте стандартным или нет.

Так что оставшаяся часть ответа будет сфокусирована (кроме того, что упомянут о противоположности) в тот факт, что он не должен происходить от классов, которые не были бы приготовлены для того, чтобы быть производными.

Возможные неудачи, разрушив объекты.

Когда класс (например: контейнер) манипулирует ресурсами (например память), должен отвечать освобождения вышеупомянутых ресурсов, предпочтительно в Вашем разрушителе.

Разрушитель объекта призван автоматически, когда этот был создан в автоматическом месте (stack), и предается область, где он был создан. Если объект был создан посредством new в динамическом месте (heap) необходимо называть разрушителя посредством инструкции delete и он тогда, когда вещи осложняются.

Мы можем хранить класс, произведенный в указателе в базовый класс, так что следующий код законный но опасный:

class Conjunto : public std::set<int> { using std::set<int>::set; };
std::set<int> *c = new Conjunto { 1, 2, 3, 4, 5 };
delete c;

Опасность содержится, в котором разрушитель std::set он не является виртуальным. Это вызывает, что, разрушив один Conjunto посредством указателя в Ваш базовый класс std::set<int> не будьте призван разрушитель женил основание и из-за этого: вся память, попросившая базовым классом остается, не освобождая. Конечно, он ничего не перемещает если Conjuto он исчезает посредством указателя в Ваш тип, или если он обосновывается в stack:

{
    Conjunto c { 1, 2, 3, 4, 5 };
    Conjunto *d = new Conjunto { c };
    std::set<int> *e = new Conjunto { c };

    // Se borra d, desde puntero a Conjunto: Ningun problema!
    delete d;
    // Se borra e, desde puntero a Conjunto: Ningun problema!
    delete static_cast<Conjunto>(e);Conjunto
}   // Se borra c automaticamente: Ningun problema!

Ввиду того, что не возможно изменять осуществление объектов книжных магазинов ajenas1, нам невозможно исправлять проблему не-виртуальности разрушителя std::set<int> и из-за этого мы можем вызывать бегство памяти, но...

И если я не хочу использовать класс с Вашего основания?

Какие недостатки имеет производить от контейнера стандарт как, например, std:: set?

Давайте предполагать, что ты не стремишься к тому, чтобы использовать твой класс формы polimórfica, это решает проблему отсутствия виртуального разрушителя. Для того, чтобы это было возможным, мы были бы должны начинаться из-за того, что меняли бы тип наследства в лишенный:

class Conjunto : private std::set<int> { using std::set<int>::set; };
// ERROR! Clase base inaccesible. No se puede asignar Conjunto a set.
std::set<int> *c = new Conjunto { 1, 2, 3, 4, 5 };

Это это рекомендуемое использование? Он это мог бы быть в каких-то контекстах, но я остаюсь без aconsejarlo2, так как он может ломать начало минимального сюрприза; как программист я подождал бы, что класс, который происходил бы std::set смогите быть использованным равно как один std::set (построенная равный, пробежавшая равный, управляемая равный); даже, если это расширение вышеупомянутого контейнера возможно включено, поставите использовать ее мне вместо std::set не мочь делать это было бы "удивительным".

Что ты советуешь? 2

Если класс ведет себя exáctamente как и другая кроме определенными операциями мы имеем различные выборы:

  • Происходить.
  • Увеличивать.
  • Составлять.

Уже мы видели pros и contras происхождения, я не считал бы это запрещенным выбором, но также не был моим первым выбором; нужно думать хорошо перед тем, как использовать ее.

C ++ он не располагает расширением классов, но могут специализироваться функции, чтобы обрабатывать информацию с некими типами и реализовывать операции, определенные на них:

// Alias de tipo, Conjunto es un set de enteros.
using Conjunto = std::set<int>;

// Funcion que recibe Conjunto como parametro
void haz_cosas(Conjunto &) { std::cout << "Es un conjunto\n"; }

// Funcion que recibe otros tipos de set como parametro
template <typename T>
void haz_cosas(std::set<T> &) { std::cout << "Esto es otra cosa\n"; }

Conjunto c { 1, 2, 3, 4, 5 };
std::set<int> s { 6, 7, 8, 9 };
std::set<float> f { .1f, .2f, .3f, .4f };

haz_cosas(c); // Muestra: Es un conjunto
haz_cosas(s); // Muestra: Es un conjunto
haz_cosas(f); // Muestra: Esto es otra cosa

К несчастью C ++ он не располагает (еще) прозвищем матовые, так что специализация haz_cosas он не отличает между Conjunto или std::set<int>.

Состав решает проблему отсутствия прозвища матовый и избегает проблемы, связанные с наследством:

// Contiene un set de enteros.
class Conjunto {
    std::set<int> datos;
    // miembros especificos
};

// Funcion que recibe Conjunto como parametro
void haz_cosas(Conjunto &) { std::cout << "Es un conjunto\n"; }

// Funcion que recibe otros tipos de set como parametro
template <typename T>
void haz_cosas(std::set<T> &) { std::cout << "Esto es otra cosa\n"; }

Conjunto c { 1, 2, 3, 4, 5 };
std::set<int> s { 6, 7, 8, 9 };
std::set<float> f { .1f, .2f, .3f, .4f };

haz_cosas(c); // Muestra: Es un conjunto
haz_cosas(s); // Muestra: Esto es otra cosa
haz_cosas(f); // Muestra: Esto es otra cosa

Почему предпочтительный состав?

Я не думаю, что выбор предпочтительный напротив другой, у него есть каждый из выборов pros и contras, чтобы иметь в виду и он будет зависеть от использования, которое захочет дать себе типу принимать решение об одной или другой.


1Poderse могут..., но: он проистекает?.

2Es личное мнение, не будь должен считаться распоряжением.

3
ответ дан 24.11.2019, 13:26
  • 1
    Спасибо за твой ответ. Верно, что частное наследство не является рекомендуемым (в ingl и # 233; s) , но не dir и # 237; в который было удивительно, что класс, который он получает в наследство лично, не может быть использованным вместо базового класса. Это часть especificaci и # 243; n языка тот, который это эксперт и # 237;. Я опускать и # 237; в эту часть, оставляя как много recomendaci и # 243; n не использования наследства, лишенного со ссылкой мотивов, для которой он хотел бы детали. – Jose Antonio Reinstate Monica 12.09.2016, 16:56
  • 2
    В самой ссылке, которую ты облегчил: " Использует composici и # 243; n, когда ты сможешь, частное наследство, когда ты будешь должен ". Это tambi и # 233; n filosof и # 237; которого я пробую вбить в мой ответ: " не создал, что opci и # 243; n будьте предпочтительным напротив другой , у него есть каждый из выборов pros и contras, чтобы иметь в виду и зависеть и # 225; использования, которое хочет дать себе типу решать на одной или другой ".: P – PaperBirdMaster 12.09.2016, 17:11
  • 3
    @JoseAntonioDuraOlmos я заканчиваюсь отчитываться, что entend и # 237; плохо твое сообщение, заниматься и # 233; издавания ответа pr и # 243; ximamente. – PaperBirdMaster 20.09.2016, 18:12

Теги

Похожие вопросы