Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > наследование операторов инкремента


Автор: Jcs 27.1.2004, 08:57
Есть базовый класс, в котором определены всякие операторы инкремента и декркмента (виртуально). Если бы его наследуем, то в дочернем классе у оных меняются типы (для постинкремета и декремента - возращается экземпляр дочернего класса, для преинкременета и декрамента - ссылка на дочерний класс).
Код

class CBase
{
public:
virtual CBase& operator++(){...}
virtual CBase& operator--(){...}

virtual CBase operator++(int){...}
virtual CBase operator--(int){...}

};
class CDeriv:public CBase
{
public:
CDeriv& operator++(){CBase::operator++();...} // all ok
CDeriv& operator--(){CBase::operator--();...}     // all ok

CDeriv operator++(int){...}           // error
CDeriv operator--(int){...}             // error
};

Компилятор для первых двух говорит, что типы виртуальных функций должны совпадать, для вторых - все нормально. Неужели единственный выход - отказ от виртуальности? Заранее спасибо.

Автор: Hroft 27.1.2004, 10:51
похоже, единственный, я другого не вижу, да и в STL они не виртуальные (файлик iterator без .h, если я все правильно понял).

Автор: RAN 27.1.2004, 11:35
Нет смысла делать operator'ы виртуальными. Их всё равно придётся перегружать для каждого конкретного типа и будет выбираться тот оператор, который подходит под тип опреранда.
Например, класс B наследуется от A. В классе A есть вирутальный оператор ++. Теперь если вызвать эту операцию для объекта B, то будет использоваться функция для типа B, а у нас определена только для A.

Код

class A
{
   virtual A& operator++ () {....}
...........................
};

class B : public A
{
...............
};

B b;
++b; //требуется функция B& operator++ (); , а мы унааследовали от A только A& operator++ ()


Теперь по поводу ошибок. Я так понял, под отказом от виртуальности ты понимаешь переписывание этих операторов для каждого класса. Это не правильный подход. Использовать функции из первого класса всё-таки можно и нужно.
Тут дело в том, что нельзя вернуть объект одного класса, как объект совсем другого класса, унаследованого от первого. Тут не проходят простые приведения типов. Класс B должен иметь конструктор от класса A для того, чтобы создать новый объект и вернуть его.
Так что добавь
Код

СDeriv( CBase& obj ) : CBase( obj ) {}

и всё заработает.

Автор: Jcs 27.1.2004, 13:26
Конструктор преобразования у меня есть.. А виртуальность я хотел использовать для того, чтобы в случае
Код

CDeriv  d_obj;
CBase b_obj;

CBase& d_obj_ref = d_obj;
CBase& b_obj_ref = b_obj;

d_obj_ref++;
b_obj_ref++;

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

Автор: RAN 27.1.2004, 21:48
Это решается по другому. Тебе надо ввести вирутальную функция для инкремента и перегрузить operator++, который будет вызывать эту функцию.

Код

class A
{
.......................
   virtual A& prefix_inc()
   {
       ........................
       return *this;
   }
   A& operator++() { return prefix_inc(); }
 
   virtual A& postfix_inc()
   {
       ................
       return *this;
   }
   A& operator++(int) { return postfix_inc(); }

};

class B : public A
{
    virtual A& prefix_inc()
    {
       .......................
        return *this;
    }
    B& operator++() { return (B&)prefix_inc(); }
   
    virtual A& postfix_inc()
    {
       ........................
       return *this;
    }
    B& operator++(int) { return (B&)postfix_inc(); }
};


И насчёт конструтора. Очень странно, что возникала ошибка. Этого не может быть. Но при подходе, описанном чуть выше, это уже не важно.

Автор: Jcs 28.1.2004, 16:05
Спасибо за ответ. Я операторы префиксного типа сделал виртуальными, т.к. они возвращают ссыклку и компилятор не ругается, а постфиксная форма легко реализуется через префиксную.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)