Перегрузка метода класса шаблона c ++ - PullRequest
2 голосов
/ 24 декабря 2010

Можно ли перегрузить функцию класса шаблона в классе, который расширяет его специализацию?

У меня есть следующий фрагмент кода (я пытался упростить его до минимума):

#include <iostream>

using namespace std;

class X {
 public:
  unsigned test_x() {
    return 1;
  }
};

class Y {
 public:
  unsigned test_y() {
    return 2;
  }
};

template <typename T, typename U>
class A {

 public: 

  unsigned foo(U i) {
    cout << "A" << endl;   
    return i.test_x();
  }

  unsigned bar(T i) {
    return foo(i);
  }

};

class B : public A<Y, X> {
 public:
  unsigned foo(Y i) {
    cout << "B" << endl;   
    return i.test_y();
  }
};

int  main() {

  B b = B();
  Y y = Y();
  cout << "Hello: " << b.bar(y) << endl;   
  return 0;

}

Однако компилятор выдает следующую ошибку:

hello.cc: In member function ‘unsigned int A<T, U>::bar(T) [with T = Y, U = X]’:
hello.cc:47:   instantiated from here
hello.cc:30: error: no matching function for call to ‘A<Y, X>::foo(Y&)’
hello.cc:24: note: candidates are: unsigned int A<T, U>::foo(U) [with T = Y, U = X]

По сути, я хотел бы перегрузить функцию A :: foo () в ее производном классе B.

Ответы [ 3 ]

5 голосов
/ 24 декабря 2010

По-видимому, то, что вы спрашиваете, называется «статическим полиморфизмом», и это достигается с помощью «любопытно повторяющегося шаблона»:

template <typename Derived, typename T, typename U>
class A {
 public:

  unsigned foo(U i) {
    cout << "A" << endl;   
    return i.test_x();
  }

  unsigned bar(T i) {
    return static_cast<Derived*>(this)->foo(i);
  }

};

class B : public A<B, Y, X> {
 public:
  // Uncomment this line if you really want to overload foo
  // instead of overriding. It's optional in this specific case.
  //using A::foo; 

  unsigned foo(Y i) {
    cout << "B" << endl;   
    return i.test_y();
  }
};
0 голосов
/ 24 декабря 2010

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

Что вы можете сделать, это извлечь метод foo, чтобы вы могли специализировать его для B.

#include <iostream>

using namespace std;

class X {
 public:
  unsigned test_x() {
    return 1;
  }
};

class Y {
 public:
  unsigned test_y() {
    return 2;
  }
};

template <typename T, typename U>
struct Foo
{
    unsigned foo(U i) {
    cout << "A" << endl;
    return i.test_x();
  }
};

template <typename T, typename U>
class A : public Foo<T, U> {

 public:
  unsigned bar(T i) {
    return this->foo(i);
  }
};

template <>
struct Foo<Y, X>
{
 public:
  unsigned foo(Y i) {
    cout << "B" << endl;
    return i.test_y();
  }
};

class B : public A<Y, X> {
};

int  main() {

  B b = B();
  Y y = Y();
  cout << "Hello: " << b.bar(y) << endl;
  return 0;
}
0 голосов
/ 24 декабря 2010

Редактировать: Мой первый ответ был неверным.

Когда вы создаете экземпляр A с классами Y и X, вызов foo(T) генерирует ошибку, поскольку в A не определен надлежащий перегруженный метод.Достаточно объявить чисто виртуальный метод foo(T) в A и реализовать этот метод в B.

template <typename T, typename U>
class A {
public: 
  virtual unsigned foo(T i) = 0;
  unsigned foo(U i) { /* as above */ }
  unsigned bar(T i) {
    return foo(i); // calls abstract foo(T)
  }
};
/* B is left untouched */

Компиляция этого генерирует этот вывод:

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