Предположим, у нас есть 2 класса:
class DataStructure {
public:
DataStructure &operator=(const DataStructure &);
friend const DataStructure &operator+(int, const DataStructure &);
//...
};
class Array : public DataStructure {
public:
Array &operator=(const DataStructure &);
friend const Array &operator+(int, const Array &);
//...
};
и мы хотим Array::operator=
а также Array
друзья operator+
сделать то же самое, что и DataStructure::operator=
а также DataStructure
друзья operator+
кроме того, что они должны вернуться Array &
,const Array &
вместо DataStructure &
,const DataStructure &
, Мне нужно сделать это с помощью десятков методов, поэтому есть ли более простой способ реализовать это, чем следующие?
Array &Array::operator=(const DataStructure &other) {
return (Array &)DataStructure::operator=(other);
}
const Array &operator+(int x, const Array &other) {
return (const Array &)(x + (DataStructure)other);
}
РЕДАКТИРОВАТЬ: У меня появилась другая идея, хотя она довольно плохая:
class Array;
class DataStructure {
public:
//...
operator Array &() const;
};
//...
DataStructure::operator Array &() const {
return (Array &)*this;
}
Сюда DataStructure
неявно преобразуется в Array
когда это необходимо, хотя он по-прежнему не может правильно обрабатывать случаи, когда оба DataStructure
а также Array
являются законными, но делают разные вещи, как в этом примере:
//in class DataStructure:
public:
friend ostream &operator<<(ostream &os,const DataStructure &)
{ os << "DataStructure" << endl; return os;}
//in class Array:
public:
friend ostream &operator<<(ostream &os,const Array &)
{ os << "Array" << endl; return os;}
//...
int main() {
Array x;
cout << 1 + x << endl;
// output: "DataStructure" instead of "Array"
return 0;
}
Спасибо вам!
Ваша реализация не хороша: operator=
должен возвращать ссылку на объект типа Array, и не должен быть виртуальным:
Array &Array::operator=(const DataStructure &other) {
DataStructure::operator=(other);
return *this;
}
Ты можешь измениться DataStructure
использовать NVI :
#include <iostream>
class DataStructure {
public:
DataStructure(){}
inline virtual ~DataStructure(){}
DataStructure &operator=(const DataStructure & other);
inline friend const DataStructure &operator+(const int a, const DataStructure & other)
{ other.add(a); return other; }
//...
private:
virtual void add( const int a ) const = 0;
};
struct Array : DataStructure
{
virtual void add( const int a ) const
{
std::cout<<"adding "<<a<<std::endl;
}
};
void foo(const DataStructure &a)
{
const DataStructure &b = 5 + a;
}
int main()
{
Array a;
foo(a);
}
Проверьте живое демо. Затем вы должны реализовать метод add
в вашем производном классе Array.
Для вашего редактирования:
Ваша новая идея — ужасный способ делать вещи в C ++. То, что вы там делаете, говорит вашему компилятору: «Хватит жаловаться, я знаю, что делаю». Кроме того, это вызывает неопределенное поведение. Может показаться, что работает, пока приложение не начнет сбой один день.
В конце концов мне удалось найти ответ. За operator=
:
class Array : public DataStructure {
public:
//...
using DataStructure::operator=;
Array &operator=(const DataStructure &);
};
Только написание Array &operator=(const DataStructure &);
будет прятаться DataStructure::operator=
, но с using
заявление это только меняет тип возвращаемого значения метода.
Замечания: using
оператор должен предшествовать строке Array &operator=(const DataStructure &);
, иначе operator=
было бы неоднозначно.
Что касается operator+
Единственное решение, которое я нашел, очень проблематично. Он использует шаблоны:
public DataStructure {
public:
template<class T> friend const T &operator+(int, const T &);
};
Например, если оригинальная реализация была
const DataStructure &operator+(int x, const DataStructure &other) {
DataStructure addition(other); /* in this example we assume
* that "DataStructure" isn't abstract */
addition.someParameter += x; /* for simplicity, assume that
* "someParameter" is public/protected */
return addition;
}
и мы хотим добиться того же результата, что и в
const Array &operator+(int x, const Array &other) {
return (const Array &)(x + (DataStructure)other);
}
чем мы можем просто написать:
template<class T>
const T &operator+(int x, const T &other) {
DataStructure addition(other); /* notice that usually we would want
* to write "T" instead of "DataStructure", but sometimes it would
* give a different result */
addition.someParameter += x;
return (const T &)addition;
}
Однако, если существует функция operator+(int,/*const*/ ThirdClass /*&*/)
это не имеет ничего общего с DataStructure
или же Array
чем мы должны были бы изменить это, что могло бы испортить код. К счастью, обычно есть только несколько дружественных функций, поэтому реализация нового метода, который выполняет преобразование (как показано в вопросе), не так уж плоха.