наследование — абстрактный базовый класс должен иметь или не иметь членов данных при использовании шаблона декоратора Переполнение стека

Некоторые посты ранее спрашивали / обсуждали, включать ли частные члены данных в абстрактные базовые классы. Я хочу исследовать это здесь на конкретном примере в сочетании с шаблоном декоратора.

Я столкнулся с этой проблемой, когда внедрял библиотеку Монте-Карло для оценки финансовых деривативов.
Генератор случайных нормальных чисел является неотъемлемой частью библиотеки ценообразования Монте-Карло. У вас есть несколько вариантов определения нормальных переменных, начиная с генератора случайных чисел, например, Вы можете использовать метод Бокса-Мюллера или обратную кумулятивную нормальную функцию, чтобы получить нормальные переменные из однородных.

Вам нужен общедоступный интерфейс, который позволяет получить 1 или более случайных переменных случайным образом, например: getRandomNormal () и getRamdomNormals (). Итак, давайте возьмем абстрактный базовый класс RandomNormalGenerator. Вы хотите хранить ваши случайные нормали в векторе, как вы хотите сделать некоторые манипуляции с ним в подклассах. Я решил также реализовать антитетическую выборку, в которой я беру сохраненные случайные нормали в классе, полученном из абстрактной базы, и меняю знак этих случайных нормалей (принцип антитетической выборки). Мой заголовочный файл выглядел так

#ifndef RANDOMNORMALGENERATOR_H_
#define RANDOMNORMALGENERATOR_H_

#include "UniformBridge.h"#include <memory>

class RandomNormalGenerator {
public:
RandomNormalGenerator();
RandomNormalGenerator(const UniformBridge& uniform_bridge);
void SetSeed(long seed);

virtual double getRandomNormal() = 0;
virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:
UniformBridge m_UBridge; // Need access to m_UBridge in derived classes.
std::vector<double> m_Normals; //Need access to m_Normals in derived classes.
private:
};

class BoxMullerGenerator: public RandomNormalGenerator {
public:
BoxMullerGenerator();
BoxMullerGenerator(const UniformBridge& uniform_bridge);
virtual double getRandomNormal();
protected:
private:
double m_Cached_value;
bool m_Cached_flag;
};

class AntitheticGenerator: public RandomNormalGenerator {
public:
AntitheticGenerator(std::unique_ptr<RandomNormalGenerator> generator);
virtual double getRandomNormal();

// getRandomNormals will generate in first go, non-antithetic sampled samples,
// when called for second time it will generate antithetic samples.
virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:

private:
AntitheticGenerator(const AntitheticGenerator&);
AntitheticGenerator& operator=(const AntitheticGenerator&);

private:
std::unique_ptr<RandomNormalGenerator> m_RandNormGenerator;
};

#endif /* RANDOMNORMALGENERATOR_H_ */

Обратите внимание, что AntitheticGenerator использует шаблон декоратора, который он наследует от абстрактного базового класса, и имеет указатель на этот абстрактный базовый класс (также подойдет обертка вокруг объекта базового класса).

AntitheticGenerator возьмет указатель, например, в BoxMuller и генерировать случайные нормали, используя BoxMuller, тогда он будет использовать случайные нормали (украшать их), сохраненные в m_Normals из BoxMuller. Конкретно, он обратит знак этих значений (если в BoxMuller был кэшированный вектор) и сохранит их в своих собственных m_Normals (m_Normals в AntitheticGenerator). Здесь делегирование вектора m_Normals абстрактному базовому классу было очень полезным, так что дублирование в подклассах не требовалось. Однако UniformBridge mUBridge (мост к генератору случайных чисел) в базовом классе не был хорошей идеей. AntitheticGenerator не нужен собственный генератор случайных чисел, поскольку он будет использовать генератор в BoxMuller … и фактически mUbridge в antitheticGenerator никогда не используется.

Так что исправленный код должен выглядеть так.

#ifndef RANDOMNORMALGENERATOR_H_
#define RANDOMNORMALGENERATOR_H_

#include "UniformBridge.h"#include <memory>

class RandomNormalGenerator {
public:
RandomNormalGenerator();
void SetSeed(long seed);

virtual double getRandomNormal() = 0;
virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:
std::vector<double> m_Normals; //Need access to m_Normals in derived classes.
private:
};

class BoxMullerGenerator: public RandomNormalGenerator {
public:
BoxMullerGenerator();
BoxMullerGenerator(const UniformBridge& uniform_bridge);
virtual double getRandomNormal();
protected:
private:
double m_Cached_value;
bool m_Cached_flag;
UniformBridge m_UBridge;
};

class AntitheticGenerator: public RandomNormalGenerator {
public:
AntitheticGenerator(std::unique_ptr<RandomNormalGenerator> generator);
virtual double getRandomNormal();

// getRandomNormals will generate in first go, non-antithetic sampled samples,
// when called for second time it will generate antithetic samples.
virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:

private:
AntitheticGenerator(const AntitheticGenerator&);
AntitheticGenerator& operator=(const AntitheticGenerator&);

private:
std::unique_ptr<RandomNormalGenerator> m_RandNormGenerator;
};

#endif /* RANDOMNORMALGENERATOR_H_ */

Заключение Используя шаблон декоратора для генерации случайных нормалей, полезно определить хранилище нормалей в базовом классе, но хранение универсального генератора случайных чисел должно быть делегировано подклассам (декорированный класс не нуждается в своем собственном).

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector