PoEdu - C++项目班 【Po学校】-Lesson02 -面向对象&多态&递归下降- 课堂笔记

 对象语义实现的两种方式

 

1-->   Node 系列类实现细节 

 1.0.0  为什么要把Node类的析构写成纯虚函数?又为什么把Node构造函数加权限隐藏呢?因为我们要设计成:只能Node的子类来进行new出来,并且不让它的对象拷贝构造,拷贝赋值。如此Node类下面的派生类,只能new出新对象,些对象具有唯一性,不可赋值,不能拷贝。如此这般特性:1,不能构造的只能new出对象设计;2,不可拷贝构造 ;3,不可拷贝赋值;4,可以被父类指针指向。具有这4个特点的类设计,就是“面向对象”的语义。

1.0.1  在Node类里面设计一个Calc()抛出deboule数值,它被设计成纯虚函数;在Node(节点)类中不需要实现它,我们可以把它看成一个路由功能(父类指针)的函数;当多态得以实现,每一个子类都有这个抛出数值的,带有路由功能的函数。

1.0.2  设计一个Node的派生类NumberNode,记得一定要实现calc(),否则些类将不可用。

1.0.3  设计一个二元类派生类BinaryNode,用此节点来存储两个元素的表达式,这个节点只有两个Node*类型的成员元素;表达式最终的计算是两个元素之间的运算,抽象出这个二元类,也是针对常量表达式计算规律的本质;为什么2个元素成员都是Node*类呢?因为Node类是系列子类的父类,可以用父类指针指向系列子类,多态特性如此。BinaryNode也继承了Node节点,也是可以利用多态的特性,以Calc()函数路由指向。这个类的精华点不仅仅如此,还有其2个成员,设计成父类Node类型的指针,也是此节点设计的一个精华所在:父类指针在父类中,代表了自己,它是一,从虚无中生出:类是虚的,new出对象来才是实体;一分二:两个可以指向父类所有派系的指针;两个指针可以是:一个元素,和一个表达式;所有常量表达式都可以解析了。

1.0.4  那么,到此时AddNode节点,应该继承哪个类?Node?还是二元类BinaryNode?看起来Node也可以选择,但是想一想:继承二元类BinaryNode是更合适的选择。因为继承了二元BinaryNode类,那么AddNode里面也就包含了父类BinaryNode的2个成员,也就包含了“三生万物”的特性。“三千大道,我只取一瓢而饮。”分析两边元素,最后返回相加的和。

1.0.5  作业:1  完善减MinusNode、乘MultipliNode、除DivideNode子类设计,思考一下:在哪里new,在哪里释放?

1.0.6  2   除法应该注意的是除数不能为0,那么怎么判断浮点数是否为0?

1.0.7  3  一元节点(负)MinusNode要怎么设计?如何返回?

 

1.1.0  具体代码实现Node系列子类(略)

 1.2.0  如此设计一个类,它有什么作用?

class NonCopyable
{
protected:
    NonCopyable(){}
private:
    NonCopyable(const NonCopyable&);  
    const NonCopyable& operator=(const NonCopyable&) = delete;      
}

1.2.1  1 上面类权限上有特点:拷贝构造与拷贝赋值都是pvivate,是子类不可见的。2 构造函数权限是protected,也就是说类外部是不可以构造对象的,那么就只能new出对象了。这正是面向对象的语义,如果一个类想达到面向对象的语义,可以继承这个类。

1.2.2  写代码注意细节 1  命名空间  2  尽量的多用const  3  注意基类的虚函数设计:要在子类实现的函数,一般多有纯虚的析构函数等。4 注意添加 override关键字。

1.2.3  分析:在哪里new出,表达式解析时new出;在哪里释放?在二元节点BinaryNode处释放,只有二元节点才知道什么时候释放。

1.2.4  对接口进行继承用private继承;

 1.2.5  在子类中直接调用父类的构造方法如:

//如下面代码中,AddNode的构造函数:AddNode(Node *left, Node *right) :BinaryNode(left, right){}
    class BinaryNode:public Node
    {
    public:
        BinaryNode(Node* left,  Node* right):left_(left),right_(right){}
        ~BinaryNode();

    protected:
        Node *left_;
        Node *right_;
    };

    class AddNode:public BinaryNode
    {
    public:
        AddNode(Node *left, Node *right) :BinaryNode(left, right){}  //直接调用父类的构造方法赋值

    };

1.2.6  注意浮点数判断除数是否为0的写法:判断一个区间。记住一个头文件<cfloat>,DBL_EPSILON这个是常用的最小值精度。

#include <cfoat>
double
DiviNode::Calc() const { double divisor = right_->Calc(); if (divisor < -DBL_EPSILON || divisor > DBL_EPSILON) { divisor = left_->Calc() / right_->Calc(); } return divisor; }

  

1.3.0  一元因子UnitaryNode类的实现

1.3.1  和二元类BinaryNode类似,一元因子也要承担起释放的任务。

1.3.2  实现一元UnitaryNode节点的子类  

 

posted on 2017-02-22 16:30  zzdoit  阅读(186)  评论(0编辑  收藏  举报

导航