使用静态const成员构建类层次结构

时间:2012-10-21 08:41:05

标签: c++ static hierarchy

我正在尝试为同余随机数生成器类创建一个合理的类层次结构(这意味着它有3个整数参数 - M a b'/ em>的)。我决定基类应该为派生类提供一个接口(所以它应该是抽象的), M a b 应该是派生类中的 static const (因为它们在派生类中是相同的)。

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

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

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();
 }

2 个答案:

答案 0 :(得分:1)

实际上你的构造没问题,它不会增加RandU类的大小。 您可以使用sizeof函数检查这是否为真:

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

返回

32
32

您可以在此处查看完整代码:http://ideone.com/HNqeOC

答案 1 :(得分: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();
}

如您所见,我从GeneralRandomGenerator派生了RandomGenerator。前者现在包含Mab的成员,而后者提供纯虚拟访问函数getM()geta()getb()。在GeneralRandomGenerator中,实现了那些访问函数以返回成员。

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

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

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

避免这种情况的一种方法是将generate()的一般化作为一个单独的函数提供给类,并将Mab作为参数传递:

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);
  }
};