[Linux]C++学习笔记(六)

[Linux]C++学习笔记(六)

在C++类中,存在隐含的this指针,在需要的时候是可以显式使用this指针的。在某些情况下必须使用this指针,而在某些时候使用this指针对操作可能会带来很大的方便。

当初始化一个类的实例,即产生一个类对象,这个类对象就是通过this指针来维护自己的数据成员的拷贝,从而不会越界操作该类的其它的类对象,而造成数据管理的混乱。

在定义类的时候,在某个成员函数中需要访问指定的成员(这里不针对静态类成员),可以直接使用类成员,而没有使用this指针,实际上已经隐含在使用this指针,只是没有显式使用,这样使用也是正确的,当然,使用“this->数据成员”来访问也是正确的。

另一种使用this指针的场合,就是可能存在一系列连续的行为,每以个行为的发生都是基于上一次发生行为返回的对象(或者对象的指针)的,也就是通过上次处理得到某个对象的一个状态,本次行为发生实在那个对象的当前状态的基础上进行的,这非常像一个链,一步一步的动作连贯起来,最后那个动作完成以后,得到的对象的状态恰好是我们需要的,直接返回就可以了。

下面以一个基于过滤链行为的例子来演示使用this指针。

过滤链的具体思想是:

针对一个集合,该集合中存放很多数据,要通过某个或者某些操作,例如对不同的过滤条件执行过滤,对原始数据集合执行过滤操作,最后得到的仍然是一个经过过滤后的集合。

设计一个Filter类,该类的设计思想阐述如下:

Filter类是针对一个list<string>容器,对字符串进行过滤。这里主要是对给定的某个数字字符在一个字符串中出现的次数的范围(一个区间),对容器中的每个字符串进行筛选。

而且,通过定义的filter成员函数,来实现链式过滤。

定义一个构造函数,初始化一个区间范围,该区间是字符串的长度区间,也就是只有当容器中的某个字符串长度在给定的这个区间之内时,才进行进一步的过滤,否则直接被排除掉。当然也定义了一个默认的构造函数,没有任何参数,这种情况下,对字符串长度的范围设置按照定义的默认值生效。

定义的Filter类的头文件Filter.h如下所示:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Filter {
        public:
                Filter();
                Filter(int slen_lower, int slen_upper);
                Filter *filter(
                        vector<string>& container,
                        const char some_char,
                        const int lower_limit,
                        const int upper_limit,
                        bool *need_check);
                ~Filter();
        private:
                int scan(string& s, const char some_char);
                bool check(string& s);
        private:
                int slen_lower;
                int slen_upper;
                static const int def_slen_lower = 1;
                static const int def_slen_upper = 100;
                bool *need_check;
};

上面定义中,默认字符串长度限制范围定义为静态私有成员:

                static const int def_slen_lower = 1;
                static const int def_slen_upper = 100;

因为int是可比较类型,可以直接定义在类的头文件中。

对于过滤行为声明为:

                Filter *filter(
                        vector<string>& container,
                        const char some_char,
                        const int lower_limit,
                        const int upper_limit,
                        bool *need_check);

bool指针类型成员need_check表示是否进行字符串长度的限制,如果为true表示进行检查,否则不考虑待过滤容器内每个字符串的长度。

Filter类的实现在Filter.cpp文件中,代码如下所示:

#include "Filter.h"

using namespace std;

Filter::Filter() : need_check(NULL) {}
Filter::Filter(int lower, int upper) : slen_lower(lower), slen_upper(upper), need_check(NULL) {}

Filter *Filter::filter(
        vector<string>& container,
        const char some_char,
        const int lower_limit,
        const int upper_limit,
        bool *need_check) {
        vector<string> v;
        vector<string>::iterator it = container.begin();

        if(this->need_check == NULL) {
                this->need_check = need_check; // 因为传入形参名与类的成员need_check相同,这里必须显式使用this指针为成员need_check赋值
        }

        while(it!=container.end()) {
                int count = scan(*it, some_char);
                if(count>=lower_limit && count<=upper_limit) {
                        v.push_back(*it);
                }
                it++;
        }
        container = v;
        return this; // 执行一次过滤后,返回当前的Filter类对象指针this,以便进一步执行过滤
}

int Filter::scan(string& s, const char some_char) {
        if(*need_check == true) {
                if(!check(s)) {
                        return -1;
                }
        }

        string::size_type size = s.size();
        int count = 0;
        string::size_type pos = s.find(some_char, 0);
        while(pos != string::npos) {
                count++;
                if(pos == size-1) {
                        break;
                }
                else {
                        pos = s.find(some_char, pos+1);
                }
        }
        return count;
}

bool Filter::check(string& s) {
        if(slen_lower <= 0 || slen_upper <= 0) {
                slen_lower = def_slen_lower;
                slen_upper = def_slen_upper;
        }
        if(s.size()>=slen_lower &&s.size()<=slen_upper ) {
                return true;
        }
        return false;
}

Filter::~Filter() {}

测试用例的设计,对容器中字符串进行如下3次连续过滤:

数字字符串'5'的个数范围:2~5
数字字符串'0'的个数范围:1~3
数字字符串'1'的个数范围:0~0

最后得到的容器中字符串的特点应该是:数字字符串'5'的个数为2~5个,并且数字字符串'0'的个数为1~3
个,同时还满足数字字符串'1'的个数为0~0个。

测试主函数如下所示:

#include <iostream>
#include <string>
#include <vector>
#include "Filter.h"

using namespace std;

int main() {
        vector<string> vtr;
        vtr.push_back("123455897000032847754524"); // 0:4 1:1 5:4
        vtr.push_back("55555555555555517"); // 0:0 1:1 5:17
        vtr.push_back("0055123510"); // 0:3 1:2 5:2
        vtr.push_back("12348934229912344320"); // 0:1 1:2 5:0
        vtr.push_back("0000055005500020"); // 0:11 1:0 5:4
        vtr.push_back("88456455532518"); // 0:0 1:1 5:5
        vtr.push_back("55223408"); // 0:1 1:0 5:2
        vtr.push_back("5504"); // 0:1 1:0 5:2
        vtr.push_back("00456455530518"); // 0:2 1:1 5:5
        vtr.push_back("01236455515"); // 0:1 1:2 5:4
        vtr.push_back("88456455532518"); // 0:0 1:1 5:5
        cout<<vtr.size()<<endl;
        int slen_lo = 2;
        int slen_up = 20;
        bool check_status = true;
        bool *need_check = &check_status;
        Filter *pfilter = new Filter(slen_lo, slen_up);
        pfilter->filter(vtr, '5', 2, 5, need_check)
                        -> filter(vtr, '0', 1, 3, need_check)
                        ->filter(vtr, '1', 0, 0, need_check);
        cout<<vtr.size()<<endl;

        vector<string>::iterator it;
        for(it=vtr.begin(); it!=vtr.end(); it++) {
                cout<<*it<<endl;
        }

        delete pfilter;
        return 0;
}

因为定义过滤行为,也就是filter方法的时候,使用了this指针,能够执行连续过滤的行为,在使用的时候,这样可以执行连续操作:

        Filter *pfilter = new Filter(slen_lo, slen_up);
        pfilter->filter(vtr, '5', 2, 5, need_check) -> filter(vtr, '0', 1, 3, need_check) ->filter(vtr, '1', 0, 0, need_check);

编译运行,如下所示:

[root@bogon pointer]# g++ -o Main *.cpp
[root@bogon pointer]# ./Main
11
2
55223408
5504

待过滤的数字字符串有11个,经过过滤,最后满足条件的只有2个,这2个字符串同时满足测试用例中三个过滤条件。

对于程序中定义的filter成员函数,我们返回的是Filter*指针,实现了连续过滤行为,当然,也可以通过返回Filter&引用来实现连续过滤行为,其实效果是一样的,只是程序的表现方式不同而已。

filter成员函数声明改成,如下所示:

Filter &filter(
                        vector<string>& container,
                        const char some_char,
                        const int lower_limit,
                        const int upper_limit,
                        bool *need_check);

同时,在Filter.cpp实现中,对filter成员函数实现的返回值,将返回语句:

return this;

修改为:

return *this;

然后在使用中调用,如下所示:

        Filter filter_ref(slen_lo, slen_up);
        filter_ref.filter(vtr, '5', 2, 5, need_check).filter(vtr, '0', 1, 3, need_check).filter(vtr, '1', 0, 0, need_check);

就是将指针运算符“->”改成了“.”运算符,执行后结果是相同的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值