Наследование методов в C++

121
03 августа 2021, 23:30

Хочу реализовать класс 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, для которого операция вычитания не определена, поэтому код упадёт. Вопрос: можно ли не переписывая методы решить эту проблему?

Answer 1

В вашем варианте надо просто вынести оператор -, сделав его свободным, а не привязывать жестко к классу, и конструктор для приведения типов:

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;
}
Answer 2

Когда вызывается оператор у класса родителя изменяются только данные этого родителя. У наследника личные данные (которые определены в классе 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; }
};
Answer 3

Проблема в том, что хотя и класс 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. Базовый класс никак не нужен пользователью наследника, поэтому тут уместнее закрытое(защищенное) наследование

READ ALSO
jQuery.get() исходный код

jQuery.get() исходный код

Как ориентироваться в src папке проекта jquery? Где я могу найти конкретно этот jQueryget метод?:

131
Развернуть список 4-х уровневый список в Laravel

Развернуть список 4-х уровневый список в Laravel

Всем привет, помогите пожалуйста реализовать данный скриптЕсть 4 уровненный список через цикл в виде Laravel

131
Wordpress некоторые картинки битые, не отображаются. Но не все

Wordpress некоторые картинки битые, не отображаются. Но не все

Wordpress некоторые картинки битые, не отображаются

138