Заменить число параметров чистых виртуальных функций

Я реализовал следующий интерфейс:

template <typename T>
class Variable
{
public:
  Variable (T v) : m_value (v) {}
  virtual void Callback () = 0;
private:
  T m_value;
};

Собственный производный класс будет определен следующим образом:

class Derived : public Variable<int>
{
public:
  Derived (int v) : Variable<int> (v) {}
  void Callback () {}
};

Однако мне хотелось бы получить классы, в которых Callback принимает разные параметры (например: void Callback (int a, int b)). Есть ли способ сделать это?

Ответы

Ответ 1

Это проблема, которую я запускал несколько раз.

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

struct Base
{
  virtual void execute() = 0;
  virtual ~Base {}
};

class Derived: public Base
{
public:
  Derived(int a, int b): mA(a), mB(b), mR(0) {}

  int getResult() const { return mR; }

  virtual void execute() { mR = mA + mB; }

private:
  int mA, mB, mR;
};

В действии:

int main(int argc, char* argv[])
{
  std::unique_ptr<Base> derived(new Derived(1,2));
  derived->execute();
  return 0;
} // main

Ответ 2

Даже если бы такая возможность была возможна, больше не имеет смысла иметь ее в качестве виртуальной функции, поскольку производные экземпляры нельзя было бы назвать полиморфно через указатель на базовый класс.

Ответ 3

Не думайте, что это будет возможно, потому что вы никогда не сможете связать его с Variable. Это то, что я имею в виду

int a=0; int b = 0;
Variable<int>* derived = new Derived();
derived->Callback(a, b); //this won't compile because Variable<int> does not have Callback with 2 vars.

Ответ 4

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

template <typename T> 
class Variable 
{ 
public: 
  Variable (T v) : m_value (v) {}
  virtual void Callback (const char *values, ...) = 0; 

private: 
  T m_value; 
};

class Derived : public Variable<int> 
{ 
public: 
  Derived (int v) : Variable<int> (v) {} 
  virtual void Callback (const char *values, ...) {
  } 
};  

Теперь вы можете использовать:

  int a=0; 
  double b = 0; 
  Variable<int>* derived = new Derived(3); 
  derived->Callback("");
  derived->Callback("df", a, b);

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

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

Ответ 5

Вам придется добавить перегрузку обратного вызова в базовый класс, который принимает эти параметры. Также можно было бы делать плохие вещи, например, принять пустоту * или передать необработанный указатель на байт. Единственный сценарий, в котором можно изменить подпись виртуальной функции, - это когда вы переопределяете возвращаемое значение на что-то полиморфное на исходное возвращаемое значение, например. * Это.