C ++, как наследовать оператор, который возвращает определенный тип - PullRequest
4 голосов
/ 30 сентября 2011

У меня есть класс 'A', который переопределяет оператор +, и подкласс 'B'.

Я хочу унаследовать оператор 'A's +, но вместо возврата типа A я хочу вернуть тип B.

Как я могу это сделать? Я попытался вызвать оператор родителя из B и привести результат к объекту A, но это не позволило мне привести родителя к потомку

Может ли мой оператор + как-то вернуть общий указатель 'A' или что-то в этом роде?

Ответы [ 3 ]

2 голосов
/ 01 октября 2011

Я часто вижу это следующим образом:

class A {
    int a;
    A(int rhs) :a(rhs) {} 
public:
    A& operator+=(const A& rhs) {a+=rhs.a; return *this} 
    A operator+(const A& rhs) {return a+rhs.a;} 
};

class B : public A {
    int b;
public:
    B(const B& rhs) :A(rhs), b(rhs.b) {}
//                               VVVVVVVVVVVVVVVVVV
    B& operator+=(const B& rhs) {A::operator+=(rhs); b+=rhs.b; return *this;}
    B operator+(const B& rhs) {return B(*this)+=rhs;}
};
2 голосов
/ 30 сентября 2011

Это могло бы - без технической причины это могло бы - это просто нарушало некоторые ожидания при использовании операторов.Так что, если это код для вас, продолжайте, но если он будет прочитан или использован другими людьми, я бы пересмотрел по следующим причинам:

  1. Ожидаемое поведение - операторы типа += и *= возвращают ссылку на объект, к которому они были вызваны после изменения этого объекта.Такие операторы, как + и *, возвращают новый объект (они в значительной степени вынуждены это делать, поскольку подразумевается, что объект, к которому они обращаются, не изменяется).Они не возвращают указатель на новый объект, потому что:
  2. Никто не ожидает их, поэтому они не будут думать о delete объекте, который они получают от оператора, что приведет к утечкам памяти,и:
  3. Вы не можете связывать операторы, которые возвращают указатели;выражение типа MyClass a = b + c + d; не будет работать, потому что тип возвращаемого значения (MyClass*) не будет соответствовать типу аргумента, который необходимо передать оператору (вероятно, const MyClass&).
  4. Возвращение ссылка на новый объект позволяет вам обходить # 3 и все еще поддерживает полиморфизм, но вы все еще застряли с # 2, и это хуже пары.То же самое относится и к перегрузке оператора, чтобы получить указатель или ссылку.

В конечном счете, просто делайте все, что делает жизнь проще для тех, кто собирается использовать код - и если это только вы, вы можетеделай что хочешь.Просто будьте осторожны, если он попадет в руки других людей, потому что они будут делать предположения.

Надеюсь, это поможет!

Редактировать: Anпример, который возвращает ссылку на новый объект:

A& A::operator + (const A& other) const
{
    A* temp = new A(); // <- This is why it's a potential memory leak
    /* Do some stuff */
    return *temp;
}

Но, имея немного больше времени на обдумывание, я бы предложил альтернативу: Определить оператор = для B, который принимаетА как его аргумент.Тогда вы можете сделать что-то вроде этого:

B b1;
B b2;
B b3 = b1 + b2;

И не имеет значения, что b1 + b2 вернул A, потому что он был преобразован обратно в B во время =.Если это работает для вас, я бы рекомендовал его выше любого другого метода, поскольку он позволяет всем операторам иметь ожидаемое поведение.

1 голос
/ 30 сентября 2011

Самый простой способ решить эту проблему - реализовать operator+ в терминах operator+=.Примерно так:

A::operator+=(const A& right) { /* stuff */ }
B::operator+=(const B& right) { static_cast<A&>(*this) += right; /* stuff */ }
operator+(B left, const B& right) { return B += right; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...