1

我正在尝试为同余随机数生成器类创建一个合理的类层次结构(这意味着它具有 3 个整数参数 - Mab)。我决定基类应该为派生类提供一个接口(所以它应该是抽象的),并且Mab应该是派生类中的静态常量(因为它们在派生类中是相同的)。

由于generate()函数对于所有同余随机数生成器都是相同的,所以它的定义应该放在基类中。问题是这个函数使用了所有的Mab,但这些不能在基类中成为static const 。

为了说明问题,提供了一种可能的解决方案。但是,我对它并不完全满意,因为它为派生类的每个实例创建了 3 个超长变量,所以我想知道是否可以提出更优雅的设计。

class RandomGenerator{
   protected:
       unsigned int seed;

       const long long int M;
       const long long int a;
       const long long int b;

   public:
       RandomGenerator(unsigned int, long long, long long, long long);

       virtual long double generate()  const = 0;
};

long double RandomGenerator::generate() const{
   static long long prv = seed;

   return (long double) (prv = (a * prv + b) % M) / (M-1);
} 

class RandU : public RandomGenerator {
    private:
       static const long long M = 2147483648LL;
       static const long long a = 65539;
       static const long long b = 0;

   public:
       RandU(unsigned int);

       virtual long double generate() const;
 };


RandU::RandU(unsigned int nseed): RandomGenerator(nseed, M, a, b){}

long double RandU::generate() const{
    return RandomGenerator::generate();
 }
4

2 回答 2

1

实际上你的构造是好的,它不会增加你的RandU类的大小。您可以使用以下sizeof功能检查是否属实:

int main() {
    cout << sizeof(RandomGenerator) << endl;
    cout << sizeof(RandU) << endl;
    return 0;
}

这返回

32
32

你可以在这里看到完整的代码:http: //ideone.com/HNqeOC

于 2012-10-21T08:48:46.650 回答
1

解决这个问题的一种方法是向层次结构中添加一个类:

class RandomGenerator {
protected:
  unsigned int seed;

public:
  RandomGenerator(unsigned int, long long, long long, long long);

  virtual long long getM() = 0;
  virtual long long geta() = 0;
  virtual long long getb() = 0;

  virtual long double generate() const;
};


inline long double RandomGenerator::generate() const {
  static long long prv = seed;
  return (long double) (prv = (a * prv + b) % M) / (M-1);
} 

class GeneralRandomGenerator : public RandomGenerator
{
  const long long int M;
  const long long int a;
  const long long int b;
public:
  virtual long long getM() { return M; }
  virtual long long geta() { return a; }
  virtual long long getb() { return b; }
};


class RandU : public RandomGenerator {
private:
  static const long long M = 2147483648LL;
  static const long long a = 65539;
  static const long long b = 0;

public:
  RandU(unsigned int);

  virtual long long getM() { return RandU::M; }
  virtual long long geta() { return RandU::a; }
  virtual long long getb() { return RandU::b; }

  virtual long double generate() const;
};


RandU::RandU(unsigned int nseed): RandomGenerator(nseed, M, a, b){}

inline long double RandU::generate() const {
  return RandomGenerator::generate();
}

如您所见,我GeneralRandomGeneratorRandomGenerator. 前者现在包含 , 和 的成员Mab后者提供纯虚拟访问功能getM(),geta()getb(). 在GeneralRandomGenerator这些访问函数中,实现了返回成员。

但是在RandU仍然从最高级别派生的 中,访问器被定义为返回静态成员的值。

这样,generate()最高级别的函数可以通过访问器函数访问它需要的内容,而值实际上来自静态或非静态成员,或者可能来自完全不同的地方。优点显然是RandU不会占用任何空间Ma并且b因为这些成员不存在于其中。

然而,缺点是即使在GeneralRandomGenerator访问M等时也是通过调用虚函数来执行的,这意味着性能比直接编码访问静态成员的性能要差。

避免这种情况的一种方法是提供泛化的 forgenerate()作为类之外的单独函数,并 passMa作为b参数:

namespace general
{
  inline long double generate(long long a, long long b, long long M) const {
    static long double prv = seed;
    return (prv = (a * prv + b) % M) / (M-1);
  }
}

class GeneralRandomGenerator
{
protected:
  unsigned int seed;

public:
  long long a;
  long long b;
  long long M;

  virtual long double generate() const {
    return general::generate(a,b,M);
  }
};

class RandomU
{
private:
  static long long a;
  static long long b;
  static long long M;
public:
  virtual long double generate() const {
    return general::generate(a,b,M);
  }
};
于 2012-10-21T09:32:21.690 回答