第一章,简单工厂模式

 首先是面向过程的代码:
感觉自己肯定就是写成这个样子了:
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char *argv[])
{
    int numberA,numberB,result;
    char Operator;
    try
    {
    cout << "please input  numberA"<<endl;
    cin >> numberA;
    cout << "plase input operator";
    cin >> Operator;
    cout << "please input numberB" << endl;
    cin >> numberB;
    switch (Operator)
    {
        case '+':
        result = numberA + numberB;
        break;
        case '-':
        result = numberA - numberB;
        break;
        case '*':
        result = numberA * numberB;
        break;
        case '/':
           if (numberB == 0)
           {
           throw 0;
           }
           result = numberA / numberB;
           break;
    }

    cout << "result is " << result;
    }
    catch (int x)
    {
    cout << "inputB 0";
    }
    catch (string error)
    {
    cout << error;
    }
}
其中使用了switch来减少判断,并且变量的名称也是使用了一般的习惯, 但是 异常的捕捉还是忘记了,静态成员函数的声明和初始化还是模糊的。
(静态成员:静态成员和静态成员函数。静态的意思就是属于一个类的 它不属于一个对象,在静态成员函数中没有this指针,也就是不能访问一般的成员。静态成员要在类的外面初始化 例如 :int A::a = 0,静态成员函数只在声明的时候用,否则出错。一般静态成员的作用是1、计数,2、标记某状态是否发生,3、存储连表第一个或者是最后一个的地址。)
(异常的捕捉,在catch中是对于异常对象的复制,并且是静态联编的,也就是会出现截断的情况,也就是在catch中要是使用的基类,那就只能使用基类的成员。catch 不是精确匹配的,是最先匹配的原则)
下面的代码是业务逻辑和页面逻辑分开的代码,这个应该是基本的层次,我都没有仔细的想。恩
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Operation
{
    public:
    static double getResult(int numberA, int numberB, char optor);
};
//static double Operation::getResult(int numbera, int numberB, char optor);?
//main.cpp:10: error: cannot declare member function ‘static void TryA::print()’ to have static linkage

double Operation::getResult(int numberA, int numberB, char optor)
{
    double result = 0.0;
    switch (optor)
    {
        case '+':
        result = numberA + numberB;
        break;
        case '-':
        result = numberA - numberB;
        break;
        case '*':
        result = numberA * numberB;
        break;
        case '/':
           result = numberA / numberB;
           break;
    }
    return result;

}

int main(int argc, char *argv[])
{
    int numberA,numberB,result;
    char Operator;
    try
    {
    cout << "please input  numberA"<<endl;
    cin >> numberA;
    cout << "plase input operator";
    cin >> Operator;
    cout << "please input numberB" << endl;
    cin >> numberB;
    if (numberB == 0 && Operator =='/')
    {
        throw 0;
    }
    result = Operation::getResult(numberA, numberB, Operator);
    cout << result;
    }
    catch (int x)
    {
    cout << "inputB 0";
    }
    catch (string error)
    {
    cout << error;
    }
}
最后是使用了简单工厂模式的代码:编程是一门艺术。和界面逻辑的分离使用了业务封装,简单工程模式 是松耦合恩(在工厂中new的东西在堆中分配,使用了多态性,内存的使用要十分小心)。


#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;//这样使用是不推荐的,会产生命名空间的污染问题。最好是不使用using namespace提示,使用哪一个成员用using声明哪一个成员,这里最好写成using std::cin;using std::cou
class Operation
{
    public:
     virtual double getResult() = 0;
     inline void setNumberA(const int &numberA){_numberA = numberA;}
     inline void setNumberB(const int &numberB){_numberB = numberB;}
    protected:
     int _numberA;
     int _numberB;

};
class OperAdd : public Operation
{
    public:
    inline virtual double getResult(){return (_numberA + _numberB);}
};
class OperSub : public Operation
{
    public:
    inline virtual double getResult(){return (_numberA - _numberB);}
};
class OperMu : public Operation
{
    public:
    inline virtual double getResult(){return (_numberA * _numberB);}
};
class OperDiv : public Operation
{
    public:
    inline virtual double getResult(){return ((_numberB == 0) ? 0 : (_numberA / _numberB));}
};
class OperFactory
{
    public:
    static Operation* getOperation(char oper);
};
Operation*  OperFactory::getOperation(char oper)
{
    Operation *tempOperation = NULL;
    switch (oper)
    {
    case '+':
       tempOperation = new OperAdd;
       break;
    case '-':
       tempOperation = new OperSub;
       break;
    case '*':
       tempOperation = new OperMu;
       break;
    case '/':
       tempOperation = new OperDiv;
       break;
    }
    return tempOperation;
}
int main(int argc, char *argv[])
{
    int numberA,numberB,result;
    char Operator;
    Operation *tmpOperation;
    try
    {
    cout << "please input  numberA"<<endl;
    cin >> numberA;
    cout << "plase input operator";
    cin >> Operator;
    cout << "please input numberB" << endl;
    cin >> numberB;
    if (numberB == 0 && Operator =='/')
    {
        throw 0;
    }
    tmpOperation = OperFactory::getOperation(Operator);
    tmpOperation -> setNumberA(numberA);
    tmpOperation -> setNumberB(numberB);
    cout << tmpOperation->getResult();

    if (tmpOperation != NULL)
    {
        delete tmpOperation;
        tmpOperation = NULL;
    }
    }
    catch (int x)
    {
    cout << "inputB 0";
    }
    catch (string error)
    {
    cout << error;
    }
}

业务逻辑应该与界面逻辑应该分开,变量名称要有含义,类的第一个字母大写,成员变量使用_开头。封装,降低耦合度
工厂要依赖于要生产的东西的。


注:在思考的过程中突然发现对于const的使用还是存在很多的问题:
在网络上找到一个讲的很直观的:
对于除指针以外的其他常量声明句法来说,
const type name

type const name
的效果是相同的, 即都声明一个类型为type名为name的常量,如:

const int x = 1;

int const x = 1;

还有

int x = 1;
const int &y = x;

int const &y = x;
都是等效的, 只是写法的风格不同而已, 有人喜欢用const type name, 比如STL的代码; 另外一些人喜欢写成type const name, 比如boost中的大量代码, 其实效果都是一样的。

对于指针来说, const出现在*号的左边还是右边或是左右都有才有区别, 具体的:

const type *p; // 一个不能修改其指向对象的type型指针
// 其实和type const *p等效

type * const p; // 一个不能修改其自身指向位置的type型指针

const type * const p;
// 一个既不能修改其指向对象也不能修改其自身指向位置的type型指针
// 也和type const * const p等效

而C++中的引用当引用了一个值后,就不能把其修改为引用另外一个值,这相当于type * const p的指针, 如:

int a, b;
int &c = a; // 声明时就和a绑定在一起
c = b; // 是把b的值赋给a, 而不是把b作为c的另一个引用

所以引用的功能其实和type * const p指针是相同的, 即其引用(指向)的位置不可改变, 如果声明引用时再加上const, 其实就相当于const type * const p型的指针了, 所以声明引用时,const type &name 和 type const &name等效的...
附录:发现了一个大虾的博文,贴下来:

const原则:在C++中最好趋向与使用const来修饰它前面的那个类型。
如:const int a;和int const b;中,虽然两种具有相同的意义,但是最好利用后面的那种情况,后面的更加可读,因为:int const我们可以很清楚地看到const是修饰int,而前面的那种方法中,我们就不那么轻易知道到底const 的具体涵义。由后面的那种方法我们可以知道const指一个恒定的整形。Int *const b,指的是一个恒定的指针b,这个指针指向一个整型,所以这个指针的内容可以改变,但是它的指针值也就是b的值不能变,相应的int const *b,指的是一个指向恒定整型内容的指针b,也就是说这个b的内容可以变,但是开始的b所指向的地址中的内容不能在程序当中通过b来改变。
volatile对上面的原则也适用。
使用类型T做为类型变量已经作为了模板参数的惯例,用来表示函数或者类所接受的类型参量可以用所有的类型。
在C++的模板的类型参量前,最好尽量使用typename来代替class。
在编译时期,模板被编译两次;
实例化之前:检查模板代码本身,查看语法是否正确;
在实例化期间,检查模板代码,查看是否所有的调用都有效。
当使用函数模板,并且引发模板实例化的时候,编译器需要查看模板定义。
在函数实参的类型的推导中,如果类型出现不匹配现象则会出现编译错误。如果要解决这编译错误则有以下几种方法解决:
对传入的实参进行类型转换成匹配类型后传入。
显示指定模板函数的全特化(不能为偏特化,因为函数不支持偏特化)类型。
例子如下所示:

template < typename T >
& max(T  & value1,T  & value2)
{

  
return value1>value2?value1:value2;
}


调用max(
3 , 4.1 )会出现编译错误,解决的办法:
1 .max(static_cast < double > ( 3 ), 4.1 );
2 .max < double > ( 3 );
3 .将函数的模板参数从一个改为两个。

在模板函数内部不能指定默认的模板参数。
函数不能采用偏特化的方法来实现类型的递归,但是它可以利用函数重载的方法来实现类型的转换。
相对于8而言类能使用偏特化的方法来实现类型的递归,并且它的仿函数也可以使用重载operator()来实现函数重载方法。但是它的一个问题就是在调用仿函数的时候一定要加上它的实例化参数类型,以及调用它的构造函数。
函数调用的时候可以采用由参数的类型来反推函数的模板参数,这是仿函数所不能的。所以我们在编程的过程当中一定要注意这些不同技术之间的优点和不足,看看哪些更适合我们。
在调用非标准函数的时候最好要与调用标准函数区分开来,这样不致于使用程序产生歧义的错误。做法是:在变量或者函数的前面加上全局标识符::。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值