面向对象的风格和基于对象的风格程序设计

下面采用两种风格实现thread类


一.基于对象的风格

先上代码:
#ifndef _THREAD_H
#define _THREAD_H

#include <pthread.h>

class thread {
public:
    thread();
    virtual ~thread();
public:
    void start();
    void join();
    virtual void run() = 0;
private:
    static void* thread_routine(void* arg);
    pthread_t tid_;
};

#endif
.cpp
#include "thread.h"
#include <iostream>
#include <assert.h>
using namespace std;

thread::thread()
{
    cout<<"thread ..."<<endl;
}

thread::~thread()
{
    cout<<"~thread ..."<<endl;
}

void thread::start()
{
    int ret = pthread_create(&tid_, NULL, thread_routine, this);
    assert(ret != -1);
}

void thread::join()
{
    pthread_join(tid_, NULL);
}

//@param : pointer to derive class
void* thread::thread_routine(void* arg)
{
    thread* th = static_cast<thread*>(arg);
  //static member function cannot directly call none member function
    th->run();
    return NULL;
}
测试函数:
#include "thread.h"

#include <unistd.h>
#include <iostream>
using namespace std;

class test_thread : public thread {
public:
    test_thread(int count) : count_(count) {
        cout<<"test_thread ..."<<endl;
    }   
    ~test_thread() {
        cout<<"~test_thread ..."<<endl;
    }   
private:
    void run() {
        while(count_--){
            cout<<"this is a test ..."<<endl;
        }   
    }   
private:
    int count_;
};

int main()
{
    test_thread t(5);
    t.start();
    t.join();
    return 0;
}


我们线程类中要使用pthread_create(),想要用run()函数作为线程运行函数。run()是普通的成员函数,隐含的第一个参数是this指针,调用的时候遵循thiscall约定,某一个寄存器会保存this指针,而prhtread_create()的线程运行函数需要调用普通入口函数。

这个问题有一下几种解决方案:

1.使用一个全局函数,但是这会向外界暴露这个函数。

2.类内部使用static修饰线程运行函数,将this指针作为pthread_create()第四个参数传递。


派生类对象调用t.start(),t调用成员函数,隐含了了一个t的this指针,调用的start()其实调用的是基类的start(),start()中pthread_create()又把this指针传给线程运行函数,所以是吧派生类对象又传到了thread_routinue(),然后在该函数中使用基类指针指向派生类对象,基类指针调用派生类实现的虚函数,这就是虚函数的多态,同时也是虚函数回调应用函数。


上面是一个派生类调用基类start()方法,基类中又回调了派生类的run()方法。静态成员函数不能调用非静态成员,不过有时我们为了实现可以传递this指针,通过this指针调用即可。


线程对象的生命周期 与 线程的生命周期是不一样的。

在栈上分配的对象生命周期是有局部作用域决定的,动态创建的对象可以使用delete销毁。


二:基于对象的编程风格

boost bind/function的出现,替代了stl中的mem_fun,ptr_fun, bind1st, bin2nd等函数,它们俩是实现基于对象编程风格的核心。

示例:

#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using namespace std;

class foo {
public:
    void member_func(double d, int i, int j) {
        cout<<d<<endl;
        cout<<i<<endl;
        cout<<j<<endl;
    }   
};

int main()
{
    foo f;
    //boost::function<void(int)> fp = boost::bind(&foo::member_func, &f, 0.5, _1, 10);  //_1相当于占位符,&f是传指针,相当于(&foo)->member_func()
    boost::function<void(int)> fp = boost::bind(&foo::member_func, boost::ref(f), 0.5, _1, 10);  //boost::ref指明它是一个引用,详单与foo.member_func()
    fp(100);  //输出0.5, 100, 10
    return 0; 
}


所以boost/bind的作用就是将一个函数接口,转换成另一种类型的函数接口,而且这个函数可以是类的成员函数,注意&符号不能没有。


基于对象的thread类参见我的这篇文章:http://blog.csdn.net/freeelinux/article/details/52916620


三:两者区别

简单理解它们的区别就是,面向对象的编程思想是不停地继承,重写,然后注册基类的回调,关联性很强。
而基于对象的编程风格就不需要继承了,我们需要在应用类中包含其他的对象。同样会注册回调。

举例注册事件到网络库:
面向对象风格,用一个EchoServer继承TcpServer(抽象类),实现相关的接口。
基于对象的风格,用一个EchoServer包含一个TcpServer(具体类)对象,可以在构造函数中使用boost::bind绑定回调函数。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值