《面向对象程序设计》课程作业七

题目描述

请将随机生成数字、表达式的部分设计成:一个Random基类,基类中有random()方法。并由该基类派生出RandomNumber类、RandomOperation类,继承并覆盖父类方法。
学习简单工厂模式,思考能否将该模式运用到题目的第一点要求中。


普通的继承!

#include<iostream>
#include<ctime>
using namespace std;

class Random {
private:
	static unsigned int seed;
public:
	void Next();
	virtual ~Random() {}
	virtual void random() = 0;
};

unsigned int Random::seed = (unsigned int)time(NULL);

void Random::Next()/*每次随机后让种子变成一个新的*/
{
	seed = seed * 11035 + 12345;
	seed = (unsigned int)(seed / 65536) % 32768;
}

class RandomNum : public Random
{
private:
	int num;
public:
	RandomNum() { num = 0; }
	virtual void random();
	int GetNum() { return num; }
};

void RandomNum::random()
{
	num = rand() % 11;
	Next();
}

class RandomOper : public Random
{
private:
	char oper;
public:
	RandomOper() { oper = '+'; }
	virtual void random();
	char GetOper() { return oper; }
};

void RandomOper::random()
{
	int choice = rand() % 4;
	switch (choice)
	{
	case'0':oper = '+'; break;
	case'1':oper = '-'; break;
	case'2':oper = '*'; break;
	case'3':oper = '/'; break;
	default:
		break;
	}
	Next();
}

int main()
{
	RandomNum rnd1;
	rnd1.random();
	cout << rnd1.GetNum() << endl;

	RandomOper rnd2;
	rnd2.random();
	cout << rnd2.GetOper() << endl;

	return 0;
}

简单工厂:

工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

工厂根据一个字符串来生成数字or运算符。

class RandomFactory
{
public:
    Random createRandom(const string &s);
    RandomFactory();
    ~RandomFactory();
};


Random * Randomfactory::creatrandom(const int & s) 
{
    if (s == "number")
    {
        return new RandomNum();
    }
    if (s == "operator")
    {
        return new RandomOper();
    }
    else
    {
        assert(false);
    }
    return NULL;
}

其余的部分逻辑相似,不贴了。

模板实现

我想到我学C#时,觉得C#自带的Random类特别方便。先创建一个Random类的对象比如rnd,然后就可以rnd.Next(int n) 生成一个随机数。

因为还要随机生成运算符,就用了模板。

一开始我还傻乎乎的以为很好写,就像下面这样:

这肯定是不行的,经过搜索,实现这样的功能要用到类模板特化的知识点。看看我的类声明:

template<class T>
class Random {
protected:
	static unsigned int seed;
public:
	static void NextSeed();
	T Next();
};

如果你传int参数进去,Next方法就生成一个随机数,如果你传的是char,那么生成一个运算符。

但对于NextSeed方法,我们不希望将其特化,因为无论对于那种类型,NextSeed的行为都希望是一样的。这就涉及到类模板的成员函数的特化。写的时候报错无数,看文档也学到了不少,在代码中也注释了方便以后重看时回忆。

github上是简单继承和模板特化的两个写法。下图是实现了C#写法的效果:


学习链接:

编译器报错文档:

编译器错误 C2910检测到尝试两次显式专用化函数C2248中不能访问访问成员声明C2352非静态成员函数的非法调用

posted @ 2017-06-08 11:41  畅畅1  阅读(341)  评论(1编辑  收藏  举报