Хочу реализовать класс Vector как сущность линейного пространства, а затем от него наследовать обычный DoubleVector и Matrix. Для этого мне бы хотелось определить метод сложения 2х объектов у родителя, но чтобы у наследника возвращался объект класса наследника. Проблема в том, что при наследовании тип возвращаемого объекта остаётся как у объекта класса родителя, но мне хотелось бы, чтобы метод наследника сразу возвращал объект класса наследника. Пример:
class A {
public:
int n{0};
A(int n) { this->n = n; }
void operator+=(const A& other) { n += other.n; }
A operator+(const A& other) {
auto res = A(this->n);
res += other;
return res;
}
};
class B: public A {
public:
B(int n): A(n) {}
void operator-=(const B& other) { n -= other.n; }
B operator-(const B& other) {
auto res = B(this->n);
res -= other;
return res;
}
};
int main() {
auto a = (B(5) + B(6)) - B(4);
std::cout << a.n << std::endl;
}
Сумма двух объектов класса B
является классом A
, для которого операция вычитания не определена, поэтому код упадёт. Вопрос: можно ли не переписывая методы решить эту проблему?
В вашем варианте надо просто вынести оператор -, сделав его свободным, а не привязывать жестко к классу, и конструктор для приведения типов:
class A {
public:
int n{0};
A(int n) { this->n = n; }
void operator+=(const A& other) { n += other.n; }
A operator+(const A& other) {
auto res = A(this->n);
res += other;
return res;
}
};
class B: public A {
public:
B(int n): A(n) {}
B(const A& a):A(a){}
void operator-=(const B& other) { n -= other.n; }
};
B operator-(const B& that, const B& other) {
auto res = B(that.n);
res -= other;
return res;
}
int main() {
auto a = (B(5) + B(6)) - B(4);
std::cout << a.n << std::endl;
}
Когда вызывается оператор у класса родителя изменяются только данные этого родителя. У наследника личные данные (которые определены в классе B) не меняются. Класс родитель ничего не знает о других наследниках, по этому возвращает себя.
Чтобы наследник возвращал себя нужно всё-таки переопределить метод. Вот так:
class B: public A {
public:
B(int n): A(n) {}
void operator-=(const B& other) { n -= other.n; }
B operator-(const B& other) {
auto res = B(this->n);
res -= other;
return res;
}
B operator+(const A& other) {
// здесь работает метод родительский
A::operator+=(other);
// возвращаем себя (наследника)
return *this; }
};
Проблема в том, что хотя и класс B
имеет оператор +
, но он возвращает обьект типа А
, а этот тип не имеет ни operator-(B)
, ни оператор преобразования в В
, для того, чтобы выполнить (B(5) + B(6)) - B(4)
. Чтобы это было возможно, оператор, определенный в базовом классе, нужно выполнить последным:
A a = B(5) + (B(6) - B(4))
Или же оператор базового класса должен возвращать другой тип, который может неявно преобразоваться в В
( вариантов можно предложить много). Вот пример на основе написанной вами:
class A {
public:
int n{ 0 };
A(int n) : n(n) { }
//возвращайте содержащийся обьект(или ссыльку)
int operator+=(const A& other)
{
n += other.n;
return n;
}
int operator+(const A& other) {
A a = *this += other;
return a.n;
}
};
class B : public A {
public:
B(int n) : A(n) {}
B operator-=(const B& other)
{
n -= other.n;
return *this;
}
// лучше оператор определить как не член класса
//она ничего не делает с данным обьектом
B operator-(const B& other) {
B b = *this -= other;
return b;
}
operator int() { return n; }
};
int main()
{
B b = (B(5) + B(6)) - B(4);
A& a = b;
std::cout << a.n << std::endl;
return exec();
}
P.S. Базовый класс никак не нужен пользователью наследника, поэтому тут уместнее закрытое(защищенное) наследование
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Как ориентироваться в src папке проекта jquery? Где я могу найти конкретно этот jQueryget метод?:
Всем привет, помогите пожалуйста реализовать данный скриптЕсть 4 уровненный список через цикл в виде Laravel
Wordpress некоторые картинки битые, не отображаются