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

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

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)). Существует ли способ сделать это?

19
задан Jir 27 May 2010 в 08:47
поделиться

5 ответов

С этой проблемой я сталкивался несколько раз.

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

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
18
ответ дан 30 November 2019 в 03:43
поделиться

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

10
ответ дан 30 November 2019 в 03:43
поделиться

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

1
ответ дан 30 November 2019 в 03:43
поделиться

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

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
ответ дан 30 November 2019 в 03:43
поделиться

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

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);

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

Этот метод склонен к ошибкам, поскольку необходимо сопоставить типы аргументов в values с реальными типами аргументов.

2
ответ дан 30 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: