Object指向函数的指针

时间:2018-05-28 10:09:20

标签: c++ pointers design-patterns

我读了一段标题代码,我在下面找到了:

ObjPtr.h:

#include <dlfcn.h>

#define OBJPTR(X)        void* X##Ptr ;         \
                            void* (*X##ObjPtr)() ;

void * CreateObj(void * handler, char* LibName, char* FunctionName);

Transaction.c

//...
OBJPTR(DB);
//...
DBObjPtr = CreateObj(DBPtr, "DBTransaction", "Function1");
if ((unsigned long)(DBObjPtr)(csPara1, csPara2) != PD_FOUND)
{
    //...

首先,我不明白头文件中定义行的含义。 (为什么定义行中有X ##?它是什么意思?)

其次,在c文件对象中创建而不是直接调用函数。我认为这种设计的目的是为了便于维护和解决方案构建/交付,在对象之间进行隔离;如果我是正确的,或者来自不同开发人员的代码加密。但还有什么?或者这种设计模式是什么样的?

1 个答案:

答案 0 :(得分:1)

##是预处理器的(!)连接。在给定的情况下,使用宏创建两个变量:

OBJPTR(DB);

将解决:

void* DBPtr;
void* (*DBObjPtr)();

实际上,我们在这里找到的并不是有效的C ++(这是你标记的问题):

  1. void* (*DBObjPtr)()声明一个接受 no 参数的函数指针,但稍后会用其中两个参数调用它。
  2. 声明的函数返回指向void的指针,但它被赋值而没有任何强制转换为函数指针。
  3. 此代码仅在C中有效(void* (*DBObjPtr)()声明一个函数指针,其中参数列表未定义;无参数函数需要显式void作为参数:void* (*x)(void)!),以及C允许从指针隐式转换为void到其他指针类型。

    意图可能在C中提供某种多态性:

    DBObjPtr = CreateObj
    (
        // probably used as some kind of handle; as not being passed
        // as pointer to pointer, the function cannot re-assign, but
        // only use it; so I assume that is has been initialized at
        // some point before this function call...
        DBPtr,
        // some kind of identifier from where to load a function from for
        // later use; as the parameter is called "library", it might load
        // the address of a function within a SO (*nix) or DLL (windows)
        "DBTransaction",
        // the name of the function to load
        "Function1"
    );
    

    在C ++中,你可能会以不同的方式处理它:

    class Loader;
    
    Loader* db = createLoader(); // initialization lacking in your sample code;
                                 // alternatively (and probably better!) via constructor
    void* (*fptr)(int, int) = db->createObj("L", "F");
    

    这还没有奏效,我们还需要应用一些改变。首先,我们需要更改函数的返回类型,它必须返回一个接受任意参数的函数指针。您可以让它返回任意参数(通过省略号)或只是有一个空参数列表 - 无所谓,您将不得不转换结果(除非使用第二个变量并且加载的函数实际上不接受任何参数。 ..)。但是从C ++ 11开始,有一种更优雅的方式可以实现这些功能,该功能可以实现为可变参数模板功能:

    class Loader
    {
    public:
        template <typename ... TT>
        auto createObj(char const*, char const*) -> void*(*)(TT ...);
    };
    

    然后将演员隐藏在该函数中,你可以简单地将其用作:

    auto f = loader->createObj<int, int>("L", "F");
    // ^ yeah, let's profit from C++11 again...
    

    只是因为你好奇:前C ++ 11方式:

    class Loader
    {
    public:
        void* (*createObj())(...);
        // function returning function pointer - ugly syntax, I know
        // (a typedef for the function pointer makes reading a little easier...)
    };
    
    void*(*f)(int, int) = reinterpret_cast<void*(*)(int, int)>(create());
    

    原始宏的最后一个注释:我个人不会使用它,即使在C中也是如此!它似乎对于懒惰的看起来很好,但实际上只是混淆了变量的声明,并且另外产生了更少类型安全的函数指针。所以我会自己声明变量:

    void* db /*= ...*/ ;
    void* (*f)(int, int) = createObj(db, "L", "F");
    //         ^    ^    already with correct parameter list