LINUX.ORG.RU

Наследование классов с параметрами себеподобного типа в методах.

 ,


0

1

Если я унаследую класс, то все его методы принмающие себеподбный класс перестанут быть корректными для наследника. Для примера операторы становятся не используемыми.

Как лучше это решается, можно ли без переписывания и переобъявления методов? Может с учетом новых с++2z?

===
UPD: Не, не работает. Например:

struct A {
   int a = 0;
   A() {}
   A(int _a) : a(_a) {}
   bool operator<(const A& other) const { return a < other.a; }
   A operator+(const A& other) const { return A(a + other.a); }
};

namespace std {
template <> struct hash<A> {
   std::size_t operator()(const A& o) const { return hash<int>()(o.a); }
}; }

struct B: public A {
   void methodOfB() const {}
};

B b1(1);
B b2(2);
(b1 + b2).methodOfB(); // <== ERROR

std::unordered_map<A,int> mapA; // normal
std::unordered_map<B,int> mapB; // <== ERROR



Последнее исправление: victor79 (всего исправлений: 3)
Ответ на: комментарий от ox55ff

Чё?

Ты никогда не наследовал класс с операторами?.. Наверное нет, иначе бы не задавал таких вопросов.

victor79
() автор топика

все его методы принмающие себеподбный класс перестанут быть корректными для наследника

Почему это?

no-such-file ★★★★★
()
Ответ на: комментарий от victor79

Ты используешь не общепризнанную терминологию. Не нужно удивляться, что тебя не понимают. Что такое «себеподобный»?

Не вижу проблем с операторами при наследовании. Наследник без проблем приводится к типу родителя. Переопределять нужно, только для расширения функциональности. Например, добавилось поле, которое нужно обработать в операторе.

Ещё почитай про ковариантность и контравариантность.

ox55ff ★★★★★
()

Если я унаследую класс, то все его методы принмающие себеподбный класс перестанут быть корректными для наследника. Для пример операторы становятся не используемыми.

Если это так ты грубо нарушаешь LSP и творишь херню. В нормальном коде операторы и все методы принимающие ссылку/указатель на себя корректно работают для любых сабклассов.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от ox55ff

Наследник без проблем приводится к типу родителя

Да, действительно, сейчас работает. Раньше не работало, давно не проверял. Но нельзя же все неработающее постоянно перепроверять. Или может для других случаев было:

class A {
public:
    int a = 1;
    void operator += (const A& o) { a += o.a; }
};

class B : public A {
public:
    int b = 2;
};
...
    A a1;
    A a2;
    a2 += a1;

    B b1;
    B b2;
    b2 += b1;
victor79
() автор топика
Ответ на: комментарий от victor79

И раньше работало. Наверное в чём то другом была ошибка.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Наверное ты объект не по ссылке или указателю принимал, а по значению.

Это вряд ли. Ну тогда вопрос решен-закрыт. Спасибо за мозговправление.

victor79
() автор топика
Ответ на: комментарий от ox55ff

Я ошибся. Скомпилируется. Это поле того же класса нельзя создать.

каким будет размер класса, если в нем поле того же класса?

или ноль, или размером со вселенную.

вообще плюсы язык циничный. они даже будут ругаться если вот так.

class A{
  int _x;
  class B{
    class C{
      class D{
        A _field;
      };
    };
  };
};

тут поле класса A обьявлено во вложенном классе, и вообще говоря такое транслируется нормально, если поля класса D в классе A - нет. если есть - опять будет бесконечная рекурсия.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.