我正在尝试为同余随机数生成器类创建一个合理的类层次结构(这意味着它有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();
}
答案 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
。前者现在包含M
,a
和b
的成员,而后者提供纯虚拟访问函数getM()
,geta()
和getb()
。在GeneralRandomGenerator
中,实现了那些访问函数以返回成员。
但是在仍然从最高级别派生的RandU
中,访问器被定义为返回静态成员的值。
这样,最高级别的generate()
函数可以通过访问器函数访问它所需的内容,而值实际上来自静态或非静态成员,或者可能来自完全不同的某个地方。明显的优势是RandU
不会为M
,a
和b
占用任何空间,因为其中不存在这些成员。
缺点然而,即使在GeneralRandomGenerator
中,通过调用虚函数来执行对M
等的访问,这意味着比通过编码可能的性能更差直接访问静态成员。
避免这种情况的一种方法是将generate()
的一般化作为一个单独的函数提供给类,并将M
,a
和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);
}
};