Как реализовать полиморфное поведение при заранее неизвестном прототипе функции?
Опишу проблему подробнее. Допустим есть базовый класс Base, и вся работа с его подклассами будет осуществляться через указатель на Base.
public:
virtual void f() {}
};
public:
void f(int x) {}
};
obj->f();
Есть подозрения, что я подхожу не правильно к проектированию. Изначально задача ставится так: есть абстрактный класс Module, от которого наследуется несколько различных классов для работы с АЦП, почти все они имеют один и тот же интерфейс, но есть специфические различия: например они имеют разные параметры (тип, количество) (можно было бы получать их в конструкторе, но их нужно изменять и в течении жизни объекта). Далее нужно работать с этими АЦП через единый интерфейс (Module), как реализовать такое поведение?
Заранее спасибо!
- Вы бы лучше интерфейсы описали. от Ramon, 28 мая 2015 года
А можно сделать так, как сказал Ramon, добавлять в классы потомки нужные поля, а метод будет иметь сигнатуру void SetupChannel(void).
#include <iostream>
#include <stdlib.h>
typedef int16_t WORD;
class Param {
public:
int ChannelNum;
WORD parameters;
double delay;
};
class Base {
public:
virtual void SetupChannel(Param *parameter) = 0;
};
class Derived1 : public Base {
public:
virtual void SetupChannel(Param *p) {
std::cout << "Derived1" << std::endl;
std::cout << "ChannelNum : " << p->ChannelNum << std::endl;
std::cout << "parameters : " << p->parameters << std::endl;
}
};
class Derived2 : public Base {
public:
virtual void SetupChannel(Param *p) {
std::cout << "Derived2" << std::endl;
std::cout << "ChannelNum : " << p->ChannelNum << std::endl;
std::cout << "delay : " << p->delay << std::endl;
}
};
int main(int argc, char** argv) {
Base *B;
Param P1,
P2;
Derived1 D1;
Derived2 D2;
P1.ChannelNum = 1;
P1.parameters = 'Ù';
P2.ChannelNum = 2;
P2.delay = 0.568;
B = &D1;
B->SetupChannel(&P1);
B = &D2;
B->SetupChannel(&P2);
system("pause");
return 0;
}
public:
virtual void SetupChannel(int ChannelNum, <тут могут появиться аргументы, на данный момент их тип и кол-во не известено> )
};
class Derived1 : public Base {
public:
virtual void SetupChannel(int ChannelNum, WORD parameters) {
//
}
};
class Derived2 : public Base {
public:
virtual void SetupChannel(int ChannelNum, double delay) {
//
}
};
};
Когда они появятся - это будет ДРУГАЯ виртуальная функция.
Я понимаю это, как можно решить такую проблему? Думаю я не первый с этим сталкиваюсь, может быть нужно смотреть в сторону какого-либо паттерна?
#include <iostream>
#include <stdlib.h>
typedef int16_t WORD;
class Param {
public:
int ChannelNum;
WORD parameters;
double delay;
};
class Base {
public:
virtual void SetupChannel(Param *parameter) = 0;
};
class Derived1 : public Base {
public:
virtual void SetupChannel(Param *p) {
std::cout << "Derived1" << std::endl;
std::cout << "ChannelNum : " << p->ChannelNum << std::endl;
std::cout << "parameters : " << p->parameters << std::endl;
}
};
class Derived2 : public Base {
public:
virtual void SetupChannel(Param *p) {
std::cout << "Derived2" << std::endl;
std::cout << "ChannelNum : " << p->ChannelNum << std::endl;
std::cout << "delay : " << p->delay << std::endl;
}
};
int main(int argc, char** argv) {
Base *B;
Param P1,
P2;
Derived1 D1;
Derived2 D2;
P1.ChannelNum = 1;
P1.parameters = 'Ù';
P2.ChannelNum = 2;
P2.delay = 0.568;
B = &D1;
B->SetupChannel(&P1);
B = &D2;
B->SetupChannel(&P2);
system("pause");
return 0;
}
Понятно, а есть ли более красивые варианты организации вспомогательного класса? Мне не нравится, что для каждого конкретного модуля будут неиспользуемые параметры (для Derived1 - delay, для Derived2 - parameters).
Спасибо!
#include <iostream>
#include <stdlib.h>
typedef int16_t WORD;
class Base {
public:
int ChannelNum;
virtual void SetupChannel(void) = 0;
};
class Derived1 : public Base {
public:
WORD parameters;
virtual void SetupChannel(void) {
std::cout << "Derived1" << std::endl;
std::cout << "ChannelNum : " << ChannelNum << std::endl;
std::cout << "parameters : " << parameters << std::endl;
}
};
class Derived2 : public Base {
public:
double delay;
virtual void SetupChannel(void) {
std::cout << "Derived2" << std::endl;
std::cout << "ChannelNum : " << ChannelNum << std::endl;
std::cout << "delay : " << delay << std::endl;
}
};
int main(int argc, char** argv) {
Base *B;
Derived1 D1;
Derived2 D2;
D1.ChannelNum = 1;
D1.parameters = 'Ù';
D2.ChannelNum = 2;
D2.delay = 0.568;
B = &D1;
B->SetupChannel();
B = &D2;
B->SetupChannel();
system("pause");
return 0;
}
В этом нет проблем, просто присваивайте новые значения соответствующим полям экземпляров классов в любое удобное время.
В этом нет проблем, просто присваивайте новые значения соответствующим полям экземпляров классов в любое удобное время.
Как мне это сделать пользуясь интерфейсом базового класса?
В этом нет проблем, просто присваивайте новые значения соответствующим полям экземпляров классов в любое удобное время.
Как мне это сделать пользуясь интерфейсом базового класса?
Создавайте объект с характерными для канала параметрами в конструкторе/убивайте объект канала.
Большое спасибо за ответы!
for(int i=2;i<8;i++){
D2.ChannelNum = i;
B->SetupChannel();
}