Переопределение членской переменной в C++

Если вы используете Java 9+ , вы можете просто использовать Optional.or:

return func1().or(() -> func2());

В Java 8 , вам может понадобиться создать новый Опциональный из результатов (используйте orElseGet, чтобы избежать нетерпеливого выполнения):

return Optional.ofNullable(func1().orElseGet(() -> func2().orElse(null)));
7
задан Bonnici 18 November 2008 в 12:18
поделиться

3 ответа

Корректный способ сделать это должно иметь переменную только в базовом классе. Поскольку производный класс знает, что должен иметь динамический тип MyVar, это полностью разумно:

class MyClass : public MyBase
{
public:
    MyClass(MyVar* v) : MyBase(v) {}
    MyVar* GetVar() { return static_cast<MyVar*>(MyBase::GetVar()); }
}

Так как MyVar получен из MyVarBase, различных типов возврата GetVar все еще работал бы, если бы GetVar был виртуальным (как имеет место здесь). Обратите внимание, что с тем методом, не должно быть никакой функции в MyBase это может сбросить указатель на что-то другое, очевидно.

Отметьте это static_cast правильный бросок в этом случае. Используя dynamic_cast, как предложено одним комментатором, скажет читателям и пользователям GetVar это MyBase::GetVar() мог возвратить указатель на объект не типа MyVar. Но это не отражает наше намерение, поскольку Вы только когда-либо передаете MyVar. Быть последовательным - самая важная вещь в разработке программного обеспечения. То, что Вы могли сделать, должно утверждать, что это является непустым. Это прервется во времени выполнения с сообщением об ошибке в сборках отладки Вашего проекта:

MyVar* GetVar() { 
    assert(dynamic_cast<MyVar*>(MyBase::GetVar()) != 0);
    return static_cast<MyVar*>(MyBase::GetVar()); 
}
13
ответ дан 6 December 2019 в 14:11
поделиться

Не зная больше контекста, трудно сказать наверняка, но я пересмотрел бы, нужна ли Вам эта иерархия классов во-первых. Вам действительно нужны классы MyVarBase и MyBase? Вам мог сойти с рук состав вместо наследования? Возможно, Вам не нужна иерархия класса вообще при шаблонной обработке функций и классов, которые работают с вышеупомянутыми классами. Возможно, CRTP может помочь также. Существует много альтернатив использованию виртуальных функций (и в некоторой степени, наследование в целом) в C++.

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

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

2
ответ дан 6 December 2019 в 14:11
поделиться

Я думаю, что Ваше упоминание о шаблонах может быть хорошим вариантом, таким образом, что-то как:

class MyVarBase
{
};

class MyVar : public MyVarBase
{
  int Foo();
};

template <class T> class MyBase
{
public: 
  MyBase(T* v) : m_var(v) {}
  T* GetVar() { return m_var; }

private:
  T* m_var;
};

class MyClass : public MyBase<MyVar>
{
public:
  MyClass(MyVar* v) : MyBase(v) {}
};

Однако это зависело бы, на каких классах можно на самом деле измениться. Кроме того, определение 'MyClass' могло быть избыточным, если оно не имеет других участников свыше класса MyBase.

0
ответ дан 6 December 2019 в 14:11
поделиться
Другие вопросы по тегам:

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