Могу ли я переопределить перегрузку оператора и вернуть другой тип? - PullRequest
1 голос
/ 16 октября 2010
class A{
  public: 
    virtual char &operator[](int);
  protected:
    ..
};
class B:A{
  public:
    A* &operator[](int);
  protected:
}

Могу ли я изменить тип возвращаемого значения при перегрузке перегрузки оператора?

спасибо! * * 1004

// EDIT Хорошо, теперь, когда мы установили, что это не будет работать, как я могу построить работу вокруг?

Допустим, у меня есть классы A, B, C и D.

class A{
  public: 
  private:
    char &operator[](int);
  protected:
    ..
};
class B:A{
  public: 
    virtual char &operator[](int);
};
class C: A{
  public:
  private:
    A::&operator[](int);
}
class D: A{
  public:
  private:
     A::&operator[](int);
}

Могу ли я сделать что-то подобное? Если это так, то правильный ли это синтаксис?

Ответы [ 4 ]

4 голосов
/ 16 октября 2010

Не так, нет.

Тип возвращаемого значения переопределения должен быть либо

  • тот же тип, что и тип возвращаемой виртуальной функции, или
  • производный класс возвращаемого типа виртуальной функции, которая переопределяется (это называется "ковариантным возвращаемым типом").

Итак, если виртуальный A::operator[] вернул A*, тогда переопределение B::operator[] может вернуть B*.

3 голосов
/ 16 октября 2010

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

Создав иерархию наследования, вы можете получить доступ к производным объектам через базовый указатель или ссылку:

class A
{
public:
    virtual char operator[](int);
};
class B : public A
{
public:
    virtual char operator[](int);
};

A *a;

std::cout << "Do you want to make an A or a B?";

char type;
std::cin >> type;

if (type == 'A')
    a = new A();
else
    a = new B();

char c = (*a)[0];

Обратите внимание, что в последней строке компилятор не будет знать, на какой тип объекта указывает a, поскольку он определяется во время выполнения. Это хорошо, потому что независимо от того, на какой тип объекта указывает a, operator[] все равно будет возвращать символ. Но что, если этому оператору было разрешено возвращать другой тип в классе B?

class Sequence
{
    ...
};

class A
{
public:
    virtual char operator[](int);
};
class B : public A
{
public:
    virtual Sequence operator[](int);
};

A *a = new B();
char c = (*a)[0];

Очевидно, что последняя строка не имеет смысла, когда a является объектом типа B. В этом случае вы пытаетесь присвоить Sequence персонажу. Аналогичным образом, Sequence c = (*a)[0]; не имеет смысла, если бы a был объектом типа A.

1 голос
/ 16 октября 2010

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

0 голосов
/ 16 октября 2010

ОК, глядя на ваш последний комментарий о Sequence (A), GeneSequence (B) и GenomeSequence (C)

вы хотите, чтобы оператор иногда возвращал char, а иногда возвращал Sequence

тогда, как вы видите, для суперкласса A неправильно объявлять тип &operator [] как char.

Он должен использовать шаблон в качестве параметра типа, чтобы указать, является ли он набором char с или Sequence с, верно?

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