Object-C多态和C++多态的简单对比

需求:两个有序集做并集,但是有序集有两种,一种是基于数组的有序集,一个是基于链表的有序集。

希望通过多态,可以让ArraySet和ArraySet求并集,ListSet和ListSet求并集,ListSet和ArraySet求并集。

 

分析:不管是基于数组的还是链表的有序集,都是可以一样的操作, 两个游标指针,在两个集合上遍历,基本就是如下的格式。

void getUnion(Set *set1, Set *set2)
{
    pos1 = set1.begin();

    pos2 = set2.begin();

    while (pos1 != set1.end() && pos2 != set2.end())

    {
        if (set1.current_value < set2.current_value)
        {
            this->insertElement(set1.current_value);
            set1.next();
            this->size++;
        }
        else if (...)
        else ...
    }

    while (pos1 != set1.end())
    {
        ...
    }

    while (pos2 != set2.end())
    {
        ...
    }
}

关键就是基于数组和基于链表在set1.insertElement(int k),set1.begin(), set1.end(), set1.next() set1.current_value()等方法的实现方法不用。所以就设置一个Set抽象类,设置这些函数的纯虚函数, 交由他的基类ArraySet,ListSet去实现。然后抽象类中自己实现getUnion函数,调用这些基础函数,来实现求并集的操作,但是这些基础函数具体怎么实现,Set类不用去管。

所以这样C++的实现就很简单。

/*
*Set抽象类
*/
class SET
{
public:
    SET(){cardinal = 0}
    virtual ~SET(){}
    
    int Cardinal() const  //集合元素个数
    {
        return cardinal;
    }
    
    bool isEmpty() const
    {
        return cardinal == 0;
    }

    bool isExist(double k) const //数据是否在集合中存在
    {
        bool flag = false;
        for (MoveToBegin(); !Eos() && !flag; MoveToNext())
        {
            if (Get() == k)
            {
                flag = true;
            }
        }
        return flag;
    }

    
    
    bool Append(double k) //添加
    {
        bool flag = false;
        if (!isExist(k))
        {
            Insert(k);
            cardinal++;
            flag = true;
        }
        return flag;
    }
    
    bool Remove(double k) //删除
    {
        bool flag = false;
        if (isExist(k))
        {
            Erease(k);
            flag = true;
            cardinal--;
        }
        return flag;
    }

    
    void Union(const SET *x, const SET *y) //求并集
    {
        Clear();
    
        x->MoveToBegin();
        y->MoveToBegin();
    
        while (!x->Eos() &&  !y->Eos())
        {
            if (x->Get() < y->Get())
            {
                Append(x->Get());
                x->MoveToNext();
            }
            else if (x->Get() > y->Get())
            {
                Append(y->Get());
                y->MoveToNext();
            }
            else
            {
                Append(x->Get());
                x->MoveToNext();
                y->MoveToNext();
            }
        }
    
        while (!x->Eos())
        {
            Append(x->Get());
            x->MoveToNext();
        }
    
        while (!y->Eos())
        {
            Append(y->Get());
            y->MoveToNext();
        }
    }
    
    void Output() const //输出
    {
        for (MoveToBegin(); !Eos(); MoveToNext())
        {
            cout << Get() << " ";
        }
        putchar(10);
    }
protected:
    mutable void *p;  //游标指针
private:
    int cardinal;
    virtual void MoveToBegin() const = 0;  //这些纯虚函数有子类实现
    virtual void MoveToEnd() const = 0;
    virtual void MoveToPrev() const = 0;
    virtual void MoveToNext() const = 0;
    
    virtual bool Bos() const = 0;
    virtual bool Eos() const = 0;
    
    virtual double Get() const = 0;
    virtual bool Set(double k) = 0;
    
    virtual bool Insert(double k) = 0;
    virtual bool Erease(double k) = 0;
    virtual void Clear() = 0;
};
/*
*ASet派生类,要具体实现Set基类的纯虚函数
*/
class ASET : public SET
{
public:
    ASET()
    {
        ele = new double[10];
        size = 10;
        length = 0;
        //cout << "ASET CONSTRUCTED" << endl;
    }
    ASET(const ASET &x)
    {
        ele = new double[x.size];
        for (int i = 0; i < x.length; i++)
        {
            ele[i] = x.ele[i];
        }
        //cout << "ASET COPY CONSTRUCTED" << endl;
    }
    virtual ~ASET()
    {
        delete [] ele;
        size = 0;
        length = 0;
        //cout << "ASET DESTRUCTED" << endl;
    }
    ASET& operator = (const ASET &x)
    {
        if (this != &x)
        {
            delete [] ele;
            ele = new double[x.size];
            for (int i = 0; i < x.length; i++)
            {
                ele[i] = x.ele[i];
            }
            length = x.length;
            size = x.size;
        }
        return *this;
    }
    
private:
    double *ele;
    int size;
    int length;
    
    virtual void MoveToBegin() const
    {
        p = ele;
    }
    virtual void MoveToEnd() const
    {
        p = (ele + length);
    }
    virtual void MoveToPrev() const
    {
        p = ((double*)p - 1);
    }
    virtual void MoveToNext() const
    {
        p = ((double*)p + 1);
    }
    
    virtual bool Bos() const
    {
        return p == ele;
    }
    virtual bool Eos() const
    {
        return p == ele + length;
    }
    
    virtual double Get() const
    {
        return *((double*)p);
    }
    virtual bool Set(double k)
    {
        bool flag = false;
        if (p >= ele && !Eos())
        {
            double *temp = (double*)p;
            *temp = k;
            flag = true;
        }
        return flag;
    }
    
    virtual bool Insert(double k)
    {
        if (length == size)
        {
            Resize(2 * size);
        }
        int i = length - 1;
        while (i >= 0)
        {
            if (ele[i] > k)
            {
                ele[i + 1] = ele[i];
            }
            else
            {
                break;
            }
            i--;
        }
        ele[i + 1] = k;
        length++;
        return true;
    }
    virtual bool Erease(double k)
    {
        bool flag = false;
        for (int i = 0; i < length; i++)
        {
            if (!flag && ele[i] == k)
            {
                flag = true;
            }
            
            if (flag && i < length - 1)
            {
                ele[i] = ele[i + 1];
            }
        }
        length -= flag;
        return flag;
    }
    virtual void Clear()
    {
        length = 0;
    }
    
    void Resize(int newsize)
    {
        double *temp = new double[newsize];
        
        for (int i = 0; i < length; i++)
        {
            temp[i] = ele[i];
        }
        
        delete [] ele;
        
        ele = temp;
        
        size = newsize;
    }
};
/*
*同理LSet类
*/
struct LNODE
{
    double k;
    LNODE *next;
    LNODE(double k, LNODE *next) : k(k), next(next){}
};

class LSET : public SET
{
public:
    LSET()
    {
        head = new LNODE(0, NULL);
        length = 0;
        //cout << "LSET CONSTRUCTED" << endl;
    }
    ~LSET()
    {
        Clear();
        delete head;
        length = 0;
        //cout << "LSET DESTRUCTED" << endl;
    }
    LSET(const LSET &x)
    {
        *this = x;
        //cout << "ASET COPY CONSTRUCTED" << endl;
    }
    
    LSET& operator = (const LSET &x)
    {
        if (&x != this)
        {
            Clear();
            
            LNODE *p = x.head->next;
            LNODE *q = this->head;
            
            while (p)
            {
                LNODE *temp = new LNODE(p->k, NULL);
                q->next = temp;
                q = q->next;
                p = p->next;
            }
            
            length = x.length;
            
        }
        return *this;
    }
    
private:
    LNODE *head;
    int length;
    
    virtual void MoveToBegin() const
    {
        p = head->next;
    }
    virtual void MoveToEnd() const
    {
        p = NULL;
    }
    virtual void MoveToPrev() const
    {
        LNODE *q = head->next;
        if (p != head->next)
        {
            for (q = head->next; q != NULL && q->next != p; q = q->next);
        }
        p = q;
    }
    virtual void MoveToNext() const
    {
        if (p != NULL)
        {
            p = reinterpret_cast<void*>(reinterpret_cast<LNODE*>(p)->next);
        }
    }
    
    virtual bool Bos() const
    {
        return p == head->next;
    }
    virtual bool Eos() const
    {
        return p == NULL;
    }
    
    virtual double Get() const
    {
        return reinterpret_cast<LNODE*>(p)->k;
    }
    virtual bool Set(double k)
    {
        int flag = false;
        if (p)
        {
            reinterpret_cast<LNODE*>(p)->k = k;
        }
        return flag;
    }
    
    virtual bool Insert(double k)
    {
        LNODE *p = head;
        bool flag = false;
        
        while (p->next)
        {
            if (p->next->k == k)
            {
                break;
            }
            else if (p->next->k < k)
            {
                p = p->next;
            }
            else
            {
                p->next = new LNODE(k, p->next);
                flag = true;
            }
        }
        if (p->next == NULL)
        {
            p->next = new LNODE(k, p->next);
            flag = true;
        }
        length += flag;
        return flag;
    }
    virtual bool Erease(double k)
    {
        bool flag = false;
        LNODE *p = head;
        
        while (p->next)
        {
            if(p->next->k == k)
            {
                LNODE *temp = p->next;
                p = temp->next;
                delete temp;
                flag = true;
            }
        }
        length -= flag;
        return flag;
    }
    virtual void Clear()
    {
        while (head->next)
        {
            LNODE *p = head->next;
            head->next = p->next;
            delete p;
        }
        length = 0;
    }

};
int main()
{
    SET *x = new ASET();
    SET *y = new LSET();
    
    SET *z = new ASET();
    
    for (int i = 0; i < 5; i++)
    {
        x->Append(1.0 * i);
    }
    
    for (int j = 0; j < 3; j++)
    {
        y->Append(2.0 * j + 1);
    }
    
    z->Union(x, y);
    
    x->Output();
    y->Output();
    z->Output();
    
    delete x;
    delete y;
    return 0;
}

在Object-C中可以用协议实现类似的方法。但是要求实现基类的程序员会实现GetUnion方法,这是一个缺点,因为实际问题中可能GetUnion方法很复杂。简单实现如下:

/*
*协议部分
*/
@protocol SetProtocal <NSObject>

- (void) nextElemen;
- (void) prevElemen;

- (void) insertElement:(int)ele;
- (void) ereaseElement:(int)ele;

- (int) getSize;
- (int) getValue;

- (void)toBegin;
- (bool)isEnd;

- (void) getUnionWith:(id<SetProtocal>) x andWith:(id<SetProtocal>)y;
- (void) Output;

- (void)clear;

@end
//-------------------------------------------------------------------------------
/*
*ArraySet
*/
@interface ArraySet : NSObject<SetProtocal>
{
    @private
    int *_ele, *_pos;
}
@property(nonatomic, assign, readonly)int size;
- (instancetype)initWith:(int)capacity;

@end
//-------------------------------------------------------------------------------
typedef struct node
{
    int data;
    struct node *next;
}node;

@interface ListSet : NSObject<SetProtocal>
{
    @private
    node *_head, *_pos;
    int _size;
    
}
- (instancetype)init;
@end
//-------------------------------------------------------------------------------
//具体类的.m文件自己实现吧。
//main
int main()
{
    id<SetProtocal> s1 = [[ListSet alloc] init];
    id<SetProtocal> s2 = [[ArraySet alloc] initWith:10];
    id<SetProtocal> s3 = [[ArraySet alloc] initWith:10];
    
    [s1 insertElement:3];
    [s1 insertElement:2];
    [s1 insertElement:4];
    [s1 Output];
    
    [s2 insertElement:1];
    [s2 insertElement:2];
    [s2 insertElement:3];
    [s2 Output];
    
    [s3 getUnionWith:s1 andWith:s2];
    [s3 Output];
    
    
    return 0;
}

 

在OC类中,由于所有函数都是虚函数,并且也可以不实现,所以也可以直接用类的特性,来实现多态。

在这个例子中,用StringNumber和汉字数字相加。”123“ + ”一二三“ = 246;

@interface Number : NSObject

-(int)toStandardInteger;
-(int)SumWith:(Number*)num1 andWith:(Number*)num2;
@property(nonatomic, strong)NSString *num;
@end

-(int)SumWith:(Number*)num1 andWith:(Number*)num2
{
    return [num1 toStandardInteger] + [num2 toStandardInteger];
}

//--------——--------——--------——--------——--------——--------——--------——

@interface StringNumber : Number
-(int)toStandardInteger;
@end

@implementation StringNumber

-(int)toStandardInteger
{
    unsigned long len = [self.num length];
    int res = 0;
    for (int i = 0; i < len; i++)
    {
        res = res * 10 + [self.num characterAtIndex:i] - '0';
    }
    return res;
}
@end

//--------——--------——--------——--------——--------——--------——--------——

@interface ChineseNumber : Number
{
    @private
    int _map[65536];
}

@end

@implementation ChineseNumber

- (instancetype)init
{
    self = [super init];
    NSString *nums = @"一二三四五六";
    _map[[nums characterAtIndex:0]] = 1;
    _map[[nums characterAtIndex:1]] = 2;
    _map[[nums characterAtIndex:2]] = 3;
    _map[[nums characterAtIndex:3]] = 4;
    _map[[nums characterAtIndex:4]] = 5;
    _map[[nums characterAtIndex:5]] = 6;
    return self;
}

-(int)toStandardInteger
{
    int len = [self.num length], res = 0;
    for (int i = 0; i < len; i++)
    {
        res = res * 10 + _map[[self.num characterAtIndex:i]];
    }
    return res;
}

@end

//---------------------------------------------------------------------------
#import <Foundation/Foundation.h>
#import "Number.h"
#import "StringNumber.h"
#import "ChineseNumber.h"
int main(int argc, const char * argv[])
{
    Number *num1 = [StringNumber new];
    Number *num2 = [ChineseNumber new];
    Number *num3 = [StringNumber new];
    num1.num = @"123";
    num2.num = @"一二三";
    
    int res = [num3 SumWith:num1 andWith:num2];
    
    NSLog(@"%d", res);
    
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值