Шаблоны для начинающих и C ++: возможно ли с помощью шаблона C ++ заставить класс, ориентированный на работу с символами, работать со структурами костюмов? - PullRequest
0 голосов
/ 23 января 2011

Так что я довольно осторожен с C ++, и я действительно не понимаю шаблонов и того, как их использовать, но я начал читать википедию на 2000 страниц на C ++ ... Так что я, вероятно, 2-й вариант, но мне интересноПри использовании шаблонов C ++ мы можем, например, заставить такую ​​простую пару классов работать со структурами костюмов вместо символов.

#include <iostream>
#include <vector>

// Boost
#include <boost/thread.hpp>

#ifndef _IGraphElementBase_h_
#define _IGraphElementBase_h_
#pragma once

using namespace std ;

class IGraphElementBase {

public:
    boost::thread GraphWorker;
    mutable boost::mutex GraphItemMutex;
    boost::condition_variable GraphItemMutexConditionVariable;
    int SleepTime;

    // Function for preparing class to work 
    virtual void Init(){ SetSleepTime(1);}

    void SetSleepTime(int timeMS)
    {
        SleepTime = timeMS;
    }

    // Function for data update // word virtual makes it possible to overwrite it
    virtual void updateData(){}


    void StartThread()
    {
        GraphWorker = boost::thread(&IGraphElementBase::Call, this);
    }

    virtual void CleanAPI(){}

    virtual void Clean()
    {
        GraphWorker.interrupt();
        GraphWorker.join();
        CleanAPI();

    }
    virtual void CastData(){}

    //Here is a main class thread function in infinite loop it calls for updateData function
    void Call()
    {
        try
        {
            for(;;){
                boost::this_thread::sleep(boost::posix_time::milliseconds(SleepTime));
                boost::mutex::scoped_lock lock(GraphItemMutex);
                boost::this_thread::interruption_point() ;

                updateData();

                lock.unlock();
                CastData();
                GraphItemMutexConditionVariable.notify_one();
            }
        }
        catch (boost::thread_interrupted)
        {
            // Thread end
        }
    }  
};

#endif // _IGraphElementBase_h_

#include "IGraphElementBase.h"

#ifndef _IGraphElement_h_
#define _IGraphElement_h_

using namespace std ;

class IGraphElement : public IGraphElementBase{

    // We should define prototype of functions that will be subscribers to our data
    typedef void FuncCharPtr(char*, int) ;

public:
    struct GetResultStructure
    {
        int length;
        char* ptr;
    };

    // initGet sets up a pointer holding a copy of pointer of data we want to return on Get() call
    void InitGet(char * pointerToUseInGetOperations, int pointerToUseInGetOperationsSize)
    {
        pointerToGet = pointerToUseInGetOperations;
        pointerToGetSize = pointerToUseInGetOperationsSize;
    }

    // Function for adding subscribers functions
    void Add(FuncCharPtr* f)
    {
        FuncVec.push_back(f);
    }

    // Returns pointer to copy of current graphItem processed data
    GetResultStructure Get()
    {
        boost::mutex::scoped_lock lock(GraphItemMutex);
        char * dataCopy = new char[pointerToGetSize];
        memcpy (dataCopy,pointerToGet,pointerToGetSize);
        lock.unlock();
        GraphItemMutexConditionVariable.notify_one();
        GetResultStructure result;
        result.ptr = dataCopy;
        result.length = pointerToGetSize;
        return result;
    }

    void Clean()
    {
        GraphWorker.interrupt();
        GraphWorker.join();
        CleanAPI();
        //delete[] pointerToGet;
        //pointerToGet = 0;

    }

    // Cast data to subscribers and clean up given pointer
    void CastData(){
        for (size_t i = 0 ; i < FuncVec.size() ; i++){
            char * dataCopy = new char[pointerToGetSize];
            memcpy (dataCopy,pointerToGet,pointerToGetSize);
            FuncVec[i] (dataCopy, pointerToGetSize) ;}
    }

    // Cast given data to subscribers and clean up given pointer
    void CastData(char * data, int length){
        for(size_t i = 0 ; i < FuncVec.size(); i++){
            char* dataCopy = new char[length];
            memcpy(dataCopy, data, length);
            FuncVec[i](dataCopy, length);
        }
    }

private:
    // Char pointer to hold a copy of pointer of data we want to return on Get() call
    char* pointerToGet;
    int pointerToGetSize;

    // Vector to hold subscribed functions
    vector<FuncCharPtr*> FuncVec ;

};
#endif // _IGraphElement_h_

Итак, что меня больше всего интересует в этих классах:

-   typedef void FuncCharPtr(char*, int) ;
-   vector<FuncCharPtr*> FuncVec ;
-   functions like void CastData(char * data, int length)

Мне действительно интересно, если есть возможность использовать шаблоны, чтобы мои классы работали со структурами костюмов.Так возможно ли и как это сделать?

1 Ответ

5 голосов
/ 23 января 2011

Шаблоны - это параметризация класса.То есть вместо множества разных классов, таких как

class myclass_int
{
   int x;
}

class myclass_double
{
   double x;
}

и т. Д.

, если вы видите шаблон, единственное, что отличается, это используемый тип, SO,мы будем использовать абстрактный тип, называемый шаблоном, в качестве своего рода заполнителя:

class myclass_T
{
    T x;
}

ЭТОТ КЛАСС НЕ ЕДИНЫЙ, а ВСЕ КОЛЛЕКЦИЯ.Если мы заменим T на int, мы получим первый класс, а T на двойной, мы получим второй.

Но когда мы создаем экземпляр myclass_T, мы должны затем указать, что на самом деле T (это в int, double и т. Д..)?

, поэтому мы определим этот параметризованный класс как

template <typename T>
class myclass
{
   T x;
}

И используем T, поскольку он уже новый, каким он был на самом деле.

Этот один класс представляет всевозможные классы, которые вы могли бы составить, которые использовали определенные типы (я дал 2 экземпляра в начале).

Шаблоны просто упрощают определение таких классов.Это намного больше, чем это, но это основа того, почему они полезны.Способ думать о шаблонном классе не как о классе, а как о «суперклассе».То есть класс, который может принимать разные представления.

Это не сложная концепция, НО, если у вас нет большого опыта работы с oop, вы можете не понять, почему они полезны, и подуматьони делают вещи более сложными.Но как только вам придётся писать очень много похожих классов, которые отличаются только используемыми типами, вы поймете, почему они так полезны (на самом деле они достаточно мощные, потому что в конечном итоге способны делать намного больше).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...