Перегрузка метода одного из предка при множественном наследовании
Есть наследник от двух предков. У обоих предков есть метод с определённым именем. Мне в наследнике нужно назначить (перегрузить) метод с таким же именем, который бы дублировал один из этих методов предка. Чтобы, вызывая метод у наследника, выполнялся одноимённый метод одного из предков. Я нагромоздил вот такую конструкцию
class Base1 {
private:
int data;
public:
int const & Data() const { return data; }
};
class Base2 {
private:
std::vector<int> data;
public:
Base2() : data{ 1,2,3,4,5,6,7,8,9,0 } {}
std::vector<int> const & Data() const & { return data ; }
std::vector<int> && Data() && { return std::move(data); }
};
class Derived: public Base1, public Base2 {
public:
std::vector<int> const & Data() const & { return Base2::Data(); }
std::vector<int> && Data() && { return std::forward<Base2>(*this).Data(); }
};
constexpr auto WWW() {
return Derived().Data().size(); // тут вызывается Base2::Data() &&
}
int main()
{
Derived obj{};
auto v1 = obj.Data(); // тут вызывается Base2::Data() const
auto v2 = Derived().Data(); // тут вызывается Base2::Data() &&
auto s = WWW();
auto v3 = Base2().Data();
}
Исправлено еще раз
Вроде работает верно (извиняюсь, сам себя обманул, а потом забыл где. исправил). Но не является ли второй метод (Data() &&
) излишним?
Может быть, раз уж я всегда возвращаю только константную ссылку на поле-член, нет смысла писать второй вариант метода с &&
? Или же без Data() &&
будут лишние копирования на v2 = Derived().Data();
? Не смог по ассемблеру понять.
Ответы (1 шт):
Или же без
Data() &&
будут лишние копирования наv2 = Derived().Data();
? Не смог по ассемблеру понять.
Не нужно разбираться в ассемблере чтобы понять. Нужно поставить вместо возвращаемого типа свой класс, с логированием в копирующем и перемещающем конструкторе. Лишние копирования действительно будут.
Еще, std::forward
тут не очень хорошо смотрится. Это условный move
, поэтому не в шаблонах обычно пишут или сразу std::move()
, или ничего. Я бы написал так: std::move(*this).Base2::Data()
. Или так: static_cast<Base2 &&>(*this).Data()
.
Еще, можно в потомке Data
вообще не определять, а просто сделать using Base2::Data;
.