Заменить число параметров чистых виртуальных функций
Я реализовал следующий интерфейс:
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
Вам придется добавить перегрузку обратного вызова в базовый класс, который принимает эти параметры. Также можно было бы делать плохие вещи, например, принять пустоту * или передать необработанный указатель на байт.
Единственный сценарий, в котором можно изменить подпись виртуальной функции, - это когда вы переопределяете возвращаемое значение на что-то полиморфное на исходное возвращаемое значение, например. * Это.