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

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


一.基于对象的风格

先上代码:
#ifndef _THREAD_H
#define _THREAD_H

#include 

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 
#include 
using namespace std;

thread::thread()
{
    cout<<"thread ..."<(arg);
  //static member function cannot directly call none member function
    th->run();
    return NULL;
}
测试函数:
#include "thread.h"

#include 
#include 
using namespace std;

class test_thread : public thread {
public:
    test_thread(int count) : count_(count) {
        cout<<"test_thread ..."<


我们线程类中要使用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 
#include 
#include 
using namespace std;

class foo {
public:
    void member_func(double d, int i, int j) {
        cout< fp = boost::bind(&foo::member_func, &f, 0.5, _1, 10);  //_1相当于占位符,&f是传指针,相当于(&foo)->member_func()
    boost::function 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绑定回调函数。


你可能感兴趣的:(Muduo源码剖析,muduo源码剖析)