C++语言中的元类编程(四)

为了方便演示,让我们先随便假定一个简单的应用场景:假定在我们的应用场景中有一个叫worker的类,它可以保存某个工人的名字,并在需要时打印出这个名字,它的源码如下:

class worker {

    char mMyName[100];

    bool mMyNameIsValid;

public:

    worker(const char * name) {

        if (name) {

            strcpy(mMyName, name);

            mMyNameIsValid = true;

        } else {

            mMyNameIsValid = false;

        }

    }

    void sayHello() {

        if (mMyNameIsValid)

            std::out << "hello, my name is " << mMyName << std::endl;

        else

            std::out << "uh...do you know who am I?" << std::endl;

    }

};

下面是主程序的源码:

int main(int argc, char * args[]) {

    for (int i = 1; i < argc; ++i) {

        worker someone(args[i]);

        someone.sayHello();

    }

    return 0;

}

下面,我们就来修改这个程序,以期待我们可以在不修改新的worker对象的实现和主程序的情况下,可以动态的植入日志。首先,我们需要定义这个worker类的元类,其中的第一步是考虑如何定义它的成员函数的问题。观察原来的worker类,它只有一个构造函数和一个sayHello函数,这两个函数都是无返回值的,回想我们之前meta_meta_closure的定义,它的模板参数中需要定义返回值类型,那么我们要如何定义无返回值的函数呢?这里需要一点模板特化的技术:

首先,我们需要定义一个表示无类型的类:

struct void_type {

};

然后,我们定义一个模板来取代sizeof():

template<typename T>
struct size_detector {

    enum {

        TYPE_SIZE = sizeof(T)

    };

};

同时,我们需要特化模板参数为void_type的情况:

template<>
struct size_detector<void_type> {

    enum {

        TYPE_SIZE = 0

    };

};

接下来,我们再定义一个新的arg_wrapper:

template<typename arg_type, typename ret_type>
struct arg_wrapper {

    arg_type args;

    ret_type retVal;

};

同样,我们需要特化模板参数为void_type的情况:

template<typename arg_type>
struct arg_wrapper<arg_type, void_type> {

    arg_type args;

};

template<typename ret_type>
struct arg_wrapper<void_type, ret_type> {

    ret_type retVal;

};

template<>

struct arg_wrapper<void_type, void_type> {

};

最后,我们需要修改一下meta_meta_closure:

template <typename closure_traits>
struct meta_meta_closure: meta_closure {

    typedef typename closure_traits::arg_type arg_type;

    typedef typename closure_traits::ret_type ret_type;

    typedef arg_wrapper<arg_type, ret_type> arg_wrapper_type;

    virtual size_t argSize() const {

        return size_detector<arg_type>::TYPE_SIZE;

    }

    virtual size_t retSize() const {

        return size_detector<ret_type>::TYPE_SIZE;

    }

    virtual void closureEntry(arg_wrapper_type * argWrapper) = 0;

    virtual void closureEntry(void * args) {

        this->closureEntry( static_cast<arg_wrapper_type *>(args) );

    }

};

这样我们就可以定义无参数或/且无返回值的函数对象了。下面给出meta_worker的完整定义:

class meta_worker: public runtime_class {

public:

    // 定义对象的数据成员:

    struct object_data {

        char mMyName[100];

        bool mMyNameIsValid;

    };

    // 因为每个成员函数都隐含了一个this指针参数,所以对每一个元函数的实现,其参数表中都需要一个this指针对应的参数,按照惯例我们总是将它命名为that

    struct meta_method_args_base {

        object_data * that;

    };

    // 定义构造函数的元函数:

    struct meta_constructor_args: meta_method_args_base {

        const char * name;

    };

    struct meta_constructor_traits {

        typedef meta_constructor_args arg_type;

        typedef void_type ret_type;

    };

    struct meta_constructor: meta_meta_closure<meta_constructor_traits> {

        virtual const char * name() const {

            static const char sName[] = "worker";

            return sName;

        }

        virtual void closureEntry(arg_wrapper_type * argWrapper) {

            if (argWrapper->name) {

                strcpy(argWrapper->that->mMyName, argWrapper->name);

                argWrapper->that->mMyNameIsValid = true;

            } else {

                argWrapper->that->mMyNameIsValid = false;

            }

        }

    };

    // 定义sayHello函数的元函数:

    struct meta_say_hello_traits {

        typedef meta_method_args_base arg_type;

        typedef void_type ret_type;

    };

    struct meta_say_hello: meta_meta_closure<meta_say_hello_traits> {

        virtual const char * name() const {

            static const char sName[] = "sayHello";

            return sName;

        }

        virtual void closureEntry(arg_wrapper_type * argWrapper) {

            if (argWrapper->that->mMyNameIsValid)

                std::out << "hello, my name is " << argWrapper->that->mMyName << std::endl;

            else

                std::out << "uh...do you know who am I?" << std::endl;

        }

    };

    // 实现接口:

    virtual const char * name() const {

        static const char sName[] = "worker";

        return sName;

    }

    virtual size_t dataSize() const {

        return sizeof(object_data);

    }

    virtual size_t methodCount() const {

        return 2;

    }

    virtual meta_closure ** methodTable() const {

        static meta_closure * sMetaMethodTable[2];

        sMetaMethodTable[0] = &mMetaConstructor;

        sMetaMethodTable[1] = &mMetaSayHello;

        return sMetaMethodTable;

    }

    virtual meta_closure * regCutPoint(meta_closure * target, bool enterOrLeave, meta_closure * cutPoint) {

        int idx = (target == &mMetaConstructor)? 0: 1;

        meta_closure ** cutPoints = enterOrLeave? mEnterPoints: mLeavePoints;

        meta_closure * ret = cutPoints[idx];

        cutPoints[idx] = cutPoint;

        return ret;

    }

    // 该类本身的实现:

    meta_worker() {

        mEnterPoints[0] = mEnterPoints[1] = mLeavePoints[0] = mLeavePoints[1] = NULL;

    }

private:

    meta_constructor mMetaConstructor;

    meta_say_hello mMetaSayHello;

    meta_closure * mEnterPoints[2];

    meta_closure * mLeavePoints[2];

};

现在,我们终于有了第一个元类的实现,让我们结合worker来理解一下这个元类,实际上,它就是对worker对象在内存中的结构以及成员函数的描述,请务必牢牢的记住并理解这一点,否则,可能会对接下来的代码示例产生误解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值