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

  • 作业链接
  • 代码地址

题目描述

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


普通的继承!

#include
#include
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) 生成一个随机数。

《面向对象程序设计》课程作业七_第1张图片

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

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

《面向对象程序设计》课程作业七_第2张图片

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

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

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

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

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

《面向对象程序设计》课程作业七_第3张图片


学习链接:

  • 类模板特化

  • 函数模板的特化

  • 类模板的成员函数及类的成员模板函数的特化

  • 模板的全特化与偏特化

编译器报错文档:

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

你可能感兴趣的:(《面向对象程序设计》课程作业七)