完全不知道怎么取标题,但是不进来看看也许会后悔--其实我一开始想写关于virtual 函数的

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014613043/article/details/51337490

假如,现在有个类,它含有数据,我们需要为它编写一些遍历的函数。
就比如,类是这样的:

class SomeClass
{
    enum{ Length = 512};
    int element[Length];
public:
    void traver()
    {
        //做一些遍历
    }
};

那如果有需求,要求遍历函数能够依据不同的情况,采取不同的遍历函数,怎么办呢?
可以让SomeClass 包含一个函数指针,通过函数指针调用函数进行遍历,还可以通过修改函数指针的值,以产生不同的遍历行为。
这个代码就不写了。但是这样有个明显的问题,如果我在函数中,还需要额外的参数呢?那怎么办?

我们可以额外声明一个抽象类,提供接口用于编写遍历函数

class DoFunc
{
public:
    virtual ~DoFunc() {}
    virtual void func(int&) = 0;
};

class Increase: public DoFunc
{
public:
    void func(int& i)
    {
        ++i;
    }
};

class Decrease: public DoFunc
{
public:
    void func(int& i)
    {
        --i;
    }
};

class SomeClass
{
    enum{ Length = 512};
    int element[Length];
    DoFunc* dofunc;


public:
    SomeClass(DoFunc* indo): dofunc(indo) {}
    void traver()
    {
        for(int i=0;i<Length;++i)
            dofunc->func(element[i]);
    }
    void setFunc(DoFunc* indo)
    {
        dofunc = indo;
    }
};

那么,对于使用这样:

    Increase in;
    Decrease de;
    SomeClass s(&in);
    //...
    s.setFunc(&de);

这是一种不错的设计方案:
这里写图片描述

至于参数,只要让DoFunc 的derived class 拥有就可以了。

除此之外,我们还可以使用模板

class Increase
{
public:
    void operator () (int& i)
    {
        ++i;
    }
};

class Decrease
{
public:
    void operator () (int& i)
    {
        --i;
    }
};

class SomeClass
{
    enum{ Length = 512};
    int element[Length];
public:
    SomeClass(){}
    template<typename T>
    void traver(T t)
    {
        for(int i=0;i<Length;++i)
            t(element[i]);
    }
};

模板能够接受的参数很多,函数指针,重载了() 操作符的类,lambda 表达式等。
那么使用可以如下:

    Increase in;
    Decrease de;
    SomeClass s;
    s.traver(in);
    s.traver(de);
    s.traver([](int& i) -> void 
    {
        i += 10;
    });

[参考资料]
[1] Scott Meyers 著, 侯捷译. Effective C++ 中文版: 改善程序技术与设计思维的 55 个有效做法[M]. 电子工业出版社, 2011.
(条款35:考虑virtual 函数以外的选择)

展开阅读全文

没有更多推荐了,返回首页