Я недавно обнаружил новое приложение 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
ключевое слово?
Это немного субъективно, поэтому давайте рассмотрим то, что мы знаем:
Если using
это правильный инструмент для работы, тогда вы должны его использовать. Это говорит:
using
будут всегда вносить все родительские методы / операторы, даже недавно добавленные, которые вы никогда не предназначали. Это может даже привести к некорректному коду, когда кто-то создает родительский оператор присваивания, который плохо взаимодействует с дочерним объектом.CStringEx
из CString
но, возможно, это намеренное поведение.Учитывая тот факт, что вы ставите его под сомнение (основываясь на том, что вы слышали) и вышеизложенное, давайте вернемся назад и посмотрим на ваш дизайн. CStringEx
имеет две возможности:
CString
объекты.