Вызов метода С++ (lvalue) привязка к функции (rvalue) в производном классе вместо функции (lvalue) в базовом классе

Я новичок в C++ и пытаюсь написать интерфейс, как показано ниже:

template <class T>
class Comparable
{
   protected:
      Comparable(){};
   public:
      virtual int compare(const T&&)=0;
      int compare(const T& o)
      {
         return this->compare(std::move(o));
      }
};

Я сделал это, чтобы попытаться заставить метод сравнения работать с обоими значениями l/r. Я получил следующий класс от Comparable:

class Monkey : Comparable<Monkey>
{
   private:
      char name[512];
   public:
      Monkey(const char*&& name)
      {
         strcpy(this->name, name);
      }
      const char *getName() { return name; }
      int compare(const Monkey&& m)
      {
         return strcmp(name, m.name);
      }
};

с помощью метода main() следующим образом:

Monkey m1(argv[1]), m2(argv[2]);
printf("\"%s\" \"%s\" %d\n", m1.getName(), m2.getName(), m2.compare(m1));

Но я получаю ошибку компиляции:

не удается связать lvalue «Tests::Monkey» с «const Tests::Monkey&&», инициализируя аргумент 1 «virtual int Tests::Monkey::compare(const Tests::Monkey&&)». Ошибка сборки

Почему вызов метода не привязан к методу сравнения в базовом классе?

Когда я создаю их как виртуальные в базовом классе и пишу их оба в производном классе, привязка работает нормально, но не работает, и я получаю ошибку компиляции, если пытаюсь скомпилировать ее так, как написано здесь.


person Joe Paul    schedule 14.03.2017    source источник
comment
Я действительно не понимаю, почему вы везде используете ссылки на rvalue. Обычная константная ссылка для функции compare будет работать нормально. И передать ссылку rvalue на const char*? Это действительно не имеет особого смысла. Наконец, постоянные ссылки на rvalue также часто не имеют смысла.   -  person Some programmer dude    schedule 14.03.2017
comment
я новичок в с++. я думаю, что ссылки предотвращают копирование, которое является поведением вызовов функций по умолчанию, поэтому я подумал, что было бы неплохо привыкнуть к их использованию и привыкнуть к ним. И я видел ссылки на const раньше. Хотя влияние на производительность, вероятно, незначительно.   -  person Joe Paul    schedule 14.03.2017
comment
@JoePaul Reference также вводит накладные расходы. Ссылка const lvalue будет идеальной в вашем случае. Ссылка rvalue в основном используется для идеальной семантики пересылки и перемещения.   -  person felix    schedule 14.03.2017


Ответы (1)


Это сокрытие имени; имя в производном классе скрывает имя в базовом классе. Короче говоря, вы не можете перегружать функции через разные области видимости.

Согласно правилу поиска неполного имени, для m2.compare(m1) m2 имеет тип Monkey сначала будет найдено имя compare в области действия производного класса Monkey, затем поиск имени остановится. compares в базовом классе вообще не будут учитываться для следующего разрешения перегрузки.

(выделено мной)

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

Вы можете ввести имена базового класса в область действия производного класса с помощью using:

class Monkey : Comparable<Monkey>
{
      ...

      using Comparable<Monkey>::compare;
      int compare(const Monkey&& m)
      {
         return strcmp(name, m.name);
      }
};
person songyuanyao    schedule 14.03.2017