наследование — C ++: как повторно использовать код в ковариантных типах возвращаемых данных?

У меня есть следующий простой класс

class base
{
public:
int x;
base &set(int y)
{
x = y;
return *this;
}
};

и хотите создать новый с дополнительной функциональностью, скажем, для печати значения х. Итак, я делаю:

class derived : public base
{
public:
void print()
{
cout << x << endl;
}
};

Теперь в основной программе я хочу сделать что-то вроде

D.set(2).print();

однако компилятор жалуется, что в базе классов нет члена с именем print.

Если я попытаюсь использовать ковариантные возвращаемые типы и напишу два класса как

class base
{
public:
int x;
virtual base &set(int y)
{
x = y;
return *this;
}
};

class derived : public base
{
public:
derived &set(int y)
{
x = y;
return *this;
}
void print()
{
cout << x << endl;
}
};

тогда оператор работает просто отлично, но я был вынужден переписать одно и то же тело функции для ‘set’ в обоих классах, хотя единственное, что меняется, — это тип возвращаемого значения.

Если позже мне потребуется изменить функциональность base :: set, то мне придется пройти через все производные классы, чтобы изменить функцию ‘set’ … Есть ли способы избежать этого? Заранее спасибо!

0

Решение

C ++ работает, как вы говорите, и вы говорите в своем базовом классе set вернуть base&Так вот что делает C ++. Но чтобы решить это, у вас есть много способов.

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

Во-вторых, вы можете обратиться к реализации базового класса как base::set поэтому код будет следующим:

class base {
...
base& set( int x ) {...}
};
class derived : public base {
derived& set( int x ) {
return static_cast<derived&>( base::set(x) );
}
};
1

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

В зависимости от ваших обстоятельств вы можете использовать CRTP:

template <class D>
class base {
D& set(int x) {
…;
return *static_cast<D*>(this);
}
};

class derived : base<derived> { … };
2

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