1. 程式人生 > >面向物件程式設計風格與基於物件程式設計風格

面向物件程式設計風格與基於物件程式設計風格

使用面向物件風格對執行緒類封裝

#ifndef _THREAD_H_
#define _THREAD_H_

#include <pthread.h>

class Thread
{
public:
    Thread();
    virtual ~Thread();

    void Start();
    void Join();

    void SetAutoDelete(bool autoDelete);

private:
    static void* ThreadRoutine(void* arg);
    virtual void Run() = 0
; // Run是普通的成員函式,隱含的第一個引數是 Thread*(this) pthread_t threadId_; bool autoDelete_; }; #endif
#include "Thread.h"
#include <iostream>
using namespace std;

Thread::Thread() : autoDelete_(false)
{
    cout << "Thread ..." << endl;
}

Thread::~Thread()
{
    cout << "~Thread ..."
<< endl; } void Thread::Start() { pthread_create(&threadId_, NULL, ThreadRoutine, this); } void Thread::Join() { pthread_join(threadId_, NULL); } void* Thread::ThreadRoutine(void* arg) // 靜態成員函式不能呼叫非靜態的成員函式 { Thread* thread = static_cast<Thread*>(arg); thread->Run(); if
(thread->autoDelete_) // 靜態成員函式不能呼叫非靜態的成員變數,使用指標訪問 delete thread; return NULL; } void Thread::SetAutoDelete(bool autoDelete) { autoDelete_ = autoDelete; }
#include "Thread.h"
#include <unistd.h>
#include <iostream>
using namespace std;

class TestThread : public Thread
{
public:
    TestThread(int count) : count_(count)
    {
        cout << "TestThread ..." << endl;
    }

    ~TestThread()
    {
        cout << "~TestThread ..." << endl;
    }

private:
    void Run()
    {
        while (count_--)
        {
            cout << "this is a test ..." << endl;
            sleep(1);
        }
    }
    int count_;
};

int main()
{
    /*
    TestThread t(5);    // 執行緒物件與執行緒的生命週期不同,執行緒物件知道程式結束才銷燬,如何讓它線上程結束後自動銷燬?
    t.Start();
    t.Join();
    */

    TestThread* t2 = new TestThread(5);
    t2->SetAutoDelete(true);
    t2->Start();
    t2->Join();

    for (; ;)
        pause();

    return 0;
}

基於物件程式設計風格對執行緒類的封裝

#ifndef _THREAD_H_
#define _THREAD_H_

#include <pthread.h>
#include <functional>

class Thread
{
public:
    typedef std::function<void ()> ThreadFunc;
    explicit Thread(const ThreadFunc& func);
    //virtual ~Thread();

    void Start();
    void Join();

    void SetAutoDelete(bool autoDelete);

private:
    static void* ThreadRoutine(void* arg);  // 類普通成員函式是thiscall呼叫約定,而ptread_create需要一個普通函式,
                                            // 因此加上static後變為普通函式,再將this指標作為引數傳遞
    void Run();     // Run是普通的成員函式,隱含的第一個引數是 Thread*(this)
    ThreadFunc func_;
    pthread_t threadId_;
    bool autoDelete_;
};

#endif
#include "Thread.h"
#include <iostream>
using namespace std;

Thread::Thread(const ThreadFunc& func) : func_(func), autoDelete_(false)
{
    cout << "Thread ..." << endl;
}

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

void Thread::Start()
{
    pthread_create(&threadId_, NULL, ThreadRoutine, this);
}

void Thread::Join()
{
    pthread_join(threadId_, NULL);
}

void* Thread::ThreadRoutine(void* arg)  // 靜態成員函式不能呼叫非靜態的成員函式
{
    Thread* thread = static_cast<Thread*>(arg);
    thread->Run();
    if (thread->autoDelete_)    // 靜態成員函式不能呼叫非靜態的成員變數,使用指標訪問
        delete thread;
    return NULL;
}

void Thread::SetAutoDelete(bool autoDelete)
{
    autoDelete_ = autoDelete;
}

void Thread::Run()
{
    func_();
}
#include "Thread.h"
#include <unistd.h>
#include <iostream>
using namespace std;

class Foo
{
public:
    Foo(int count) : count_(count)
    {
        cout << "Foo ..." << endl;
    }

    void MemberFun()
    {
        while (count_--)
        {
            cout << "this is a test ..." << endl;
            sleep(1);
        }
    }

    int count_;
};

void ThreadFunc()
{
    cout << "ThreadFunc ..." << endl;
}
void ThreadFunc2(int count)
{
    while (count--)
    {
        cout << "ThreadFunc2 ..." << endl;
        sleep(1);
    }
}

int main()
{
    Thread t1(ThreadFunc);
    Thread t2(std::bind(ThreadFunc2, 3));   // 普通函式引數取地址可省略
    Foo foo(3);
    Thread t3(std::bind(&Foo::MemberFun, &foo));    // 成員函式取地址不可省略,&foo為省略引數,相當於this指標
    t1.Start();
    t2.Start();
    t3.Start();
    t1.Join();
    t2.Join();
    t3.Join();

    return 0;
}

總結:
面向物件的程式設計會暴露抽象類,利用虛擬函式的多型性回撥相應介面
基於物件的程式設計只使用具體類,不暴露抽象類,應用類並不是繼承抽象類,而是包含一個具體類的物件,然後將具體類的實現繫結為相應的回撥