Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)
Paste
Pasted as C++ by Somebody ( 15 years ago )
#include <iostream>
#include <limits>
#include <cmath>
/* "Конвейер обработки данных"
источник --> стадия1 --> ...
--> стадияN --> потребитель
передаются "объекты данных"
Интерфейсы:
"данные" -- IData
"источник" -- ISource
"потребитель" -- IConsumer
стадия i -- источник для стадии i+1
-- потребитель для стадии i-1
-- реализует (наследует) одновременно
ISource и IConsumer
*/
// интерфейсы
struct IData // интерфейс "данные"
{
virtual ~IData() {}
// создать копию в динамической памяти
virtual IData* clone() const = 0;
// сравнить на равенство
virtual bool operator==(const IData &right;) const = 0;
bool operator!=(const IData &right;) const
{
return !(*this == right);//!this->operator==(right)
}
// вывести содержимое в поток в текстовой форме
virtual void write(std::ostream &os;) const = 0;
};
struct IConsumer // интерфейс "потребитель"
{
virtual ~IConsumer() {}
// потребить данные
virtual void consume(IData *data) = 0;
};
struct ISource // интерфейс "источник"
{
virtual ~ISource() {}
// подключить потребителя, возвращает предыдущего
virtual IConsumer* attach(IConsumer*) = 0;
// сгенерировать данные и передать потребителю
virtual void run() = 0;
};
// реализует только attach
class AbstractSource: public ISource
{
protected:
IConsumer *consumer;
public:
AbstractSource() // сначала consumer = 0
: consumer(nullptr) {} // замена NULL
IConsumer* attach(IConsumer *newConsumer)
{
IConsumer *oldConsumer = consumer;
consumer = newConsumer;
return oldConsumer;
}
};
// потомки с функциональностью
struct Double: IData // wrapper (to wrap)
{
double value;
Double(double val = 0.0) // конструктор
: value(val) {} // value = 0 по умолчанию
IData* clone() const
{
return new Double(value);
}
bool operator==(const IData &right;) const
{
if (auto p = dynamic_cast<const Double*>(&right;))
return p->value == value;
return false;
}
void write(std::ostream &os;) const
{
os << value << std::endl;
}
};
struct Cout: IConsumer // пишет в cout
{
void consume(IData *data)
{
data->write(std::cout);
delete data;
}
};
// читает double с cin, оборачивает в Double
struct DoublesFromCin: AbstractSource
{
void run()
{
double value // set to "not a number" value
= std::numeric_limits<double>::quiet_NaN();
std::cin >> value;
if (std::cin.eof())
return;
else if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore();
}
else if (consumer) // не нулевой => есть потребитель
consumer->consume(new Double(value));
}
};
class MyFormula
: public AbstractSource, public IConsumer
{
double fvalue;
public:
void consume(IData *data)
{
if (auto p = dynamic_cast<Double*>(data))
fvalue = std::log(1.0 + std::sin(p->value));
delete data;
run();
}
void run()
{
if (consumer) // не нулевой => есть потребитель
consumer->consume(new Double(fvalue));
}
};
int main()
{
// сборка конвейера
DoublesFromCin convCin;
MyFormula convStage1;
Cout convCout;
convStage1.attach(&convCout;);
convCin.attach(&convStage1;); // присоединить потребителя
// прогонка конвейера
for (; !std::cin.eof(); )
convCin.run();
}
Revise this Paste