наследование — Недостатки ключевого слова «Использование» в C ++ применительно к производным классам

Я недавно обнаружил новое приложение using ключевое слово; не со ссылкой на namespace функциональность, но внутри объявления производного класса. В моем случае это было уместно в отношении проблем, связанных с функцией-члена operator =.

У меня была ситуация, когда, учитывая декларации:

class CString{
public:
...//Various functions.
operator=(const CString &cString)
{
//code to share internal array and increment reference count
}
operator=(const wchar_t *pstrString)
{
//code to create a personal internal array,
//resize it appropriately and copy the pstrString argument.
}
...
};

class CStringEx : public CString{
...//various members that expand upon CString's abilities.
};

…объект CStringEx не работает, как я ожидал:

CStringEx cString;

cString=L"String contents";

Вместо этого была сгенерирована ошибка компилятора:CStringEx не имеет функции operator = (), которая принимает аргумент типа wchar_t *‘(или — очень близко — слова на этот счет). После долгого изучения я узнал, что это потому, что даже автоматически сгенерированный компилятором operator= Функции-члены производного класса переопределяют функции, унаследованные от его родительского класса. Это кажется нелогичным иООНдружелюбен ко мне.

Однако, если я добавлю using ключевое слово:

class CStringEx : public CString{
public:
using CString::operator=;
...
};

…детский класс будут Теперь используйте его родителей operator= функция-член и все хорошо.

Все идет нормально. Однако после прочтения здесь и в других местах я узнал, что многие программисты не любят использовать using для этого. Например, я читал некоторые комментаторы, которые описывают потенциально нежелательные побочные эффекты, такие как слияние во ВСЕХ операторах = от родителя. Однако, опять же, за исключением очень специфических обстоятельств, я не понимаю, почему наследование всех родительских функций-членов было бы и проблематичным. Если это главная проблема, может ли кто-нибудь объяснить общие опасности этого?

Единственная альтернатива, о которой я могу подумать, — выписать функции-заглушки в дочернем классе для каждый operator= функция-член его родителя, а затем явно вызвать соответствующие функции-члены:

class CStringEx : public CString{
public:
...
const CStringEx& operator=(const wchar_t* pstrString)
{
CString::operator=(pstrString);
return *this;
}
const CStringEx& operator=(const CString &cString)
{
CString::operator=(cString);
return *this;
}
...//and so on...
};

По сравнению с версией с using CString::operator= это выглядит очень уродливо, громоздко и грязно для меня. Итак, еще раз, почему бы не использовать using ключевое слово?

7

Решение

Это немного субъективно, поэтому давайте рассмотрим то, что мы знаем:

Если using это правильный инструмент для работы, тогда вы должны его использовать. Это говорит:

  • using будут всегда вносить все родительские методы / операторы, даже недавно добавленные, которые вы никогда не предназначали. Это может даже привести к некорректному коду, когда кто-то создает родительский оператор присваивания, который плохо взаимодействует с дочерним объектом.
  • Ввод оператора родительского копирования означает, что вы можете создать CStringEx из CString но, возможно, это намеренное поведение.
  • Будущие читатели / сопровождающие могут быть не знакомы с оператором, использующим синтаксис, и могут немного усложнить выполнение кода.

Учитывая тот факт, что вы ставите его под сомнение (основываясь на том, что вы слышали) и вышеизложенное, давайте вернемся назад и посмотрим на ваш дизайн. CStringEx имеет две возможности:

  1. Он имеет дополнительные данные членов. В этом случае я хочу заявить, что наследование родительских операторов в некоторых или во всех случаях приведет к ошибкам, поскольку члены дочернего класса не будут обрабатываться в назначении.
  2. Он не имеет дополнительных элементов данных, он только обеспечивает дополнительную функциональность кода. В этом случае, пожалуйста, не поддавайтесь искушению использовать дочерний класс. Вместо этого напишите алгоритмы свободных функций, которые работают в диапазонах (итераторов) или, если необходимо, CString объекты.
1

Другие решения


По вопросам рекламы [email protected]