代码之家  ›  专栏  ›  技术社区  ›  Patrick

C++中函数/方法/模板名称的优先选择是什么?

  •  2
  • Patrick  · 技术社区  · 15 年前

    如果有多种可能性,C++编译器如何决定调用哪个函数/方法? 在我的特定情况下,我具有C++运行时的标准自由函数,并且我也有一个模板化的自由变量,如下所示:

    // The definitions of the C++ Run Time Library (from memory.h)
    extern malloc(size_t s);
    extern void free(void *p);
    
    // Our own memory management functions
    extern void *OurMalloc(size_t s);
    extern void OurFree(void *p);
    
    // Own variants to overrule malloc and free (instead of using #define)
    template<typename T>
    void *malloc(T t)
    {
    return OurMalloc(t);
    }
    
    template<typename T>
    void free(T *t)
    {
    OurFree(t);
    }
    

    我用以下代码测试了这个:

    void main(void)
    {
    void *p = malloc(10);
    free(p);
    }
    

    如果我编译并运行它,那么对malloc的调用似乎被模板化变量正确替换了。到目前为止,一切都很好。

    但是,调用的自由并不被模板化的变体所替代,标准的C++函数仍然被调用。

    C++编译器使用什么规则来决定哪一个变量优先? 这与Koenig查找规则有关吗?

    注意:我尝试了这种方法,因为使用define不能解决问题(请参见问题 How to use C macro's (#define) to alter calls but not prototypes )

    4 回复  |  直到 14 年前
        1
  •  8
  •   AProgrammer    15 年前

    过载分辨率通常相当复杂。

    在您的例子中,这是非常简单的:如果有一个完全匹配的函数模板,则不考虑它。对于free,情况就是这样(标准free取空*),对于malloc则不是(标准malloc取大小t,您传递的是int,而大小t不能是int的typedef--大小t不带符号)。如果使用void*以外的类型调用free,它应该实例化模板。

    运行:

    #include <iostream>
    
    void* ml(size_t s)
    {
        std::cout << "ml(size_t)\n";
    }
    
    void fr(void *p)
    {
        std::cout << "fr(void*)\n";
    }
    
    template<typename T>
    void* ml(T t)
    {
        std::cout << "ml<" << typeid(T).name() << ">(T)\n";
    }
    
    template<typename T>
    void fr(T *t)
    {
        std::cout << "fr<" << typeid(T).name() << ">(T*)\n";
    }
    
    int main()
    {
        void* p1 = ml((size_t)10);
        fr(p1);
        int* p2 = (int*)ml(10);
        fr(p2);
        return 0;
    }
    

    我明白了

    ml(size_t)
    fr(void*)
    ml<i>(T)
    fr<i>(T*)
    

    我就是回报 typeid(int).name()

        2
  •  3
  •   Michael Burr    15 年前

    关于你的特殊问题 malloc free ,问题是你打电话给 马洛克 :

    void *p = malloc(10);
    

    参数10的类型为 int ,而运行时的 malloc() 呼唤一个 unsigned 争论。由于没有完全匹配,编译器更喜欢模板化的 马洛克 在那里它可以创建一个精确的匹配。

    当你打电话:

    free(p);
    

    的类型 p void* 与运行时的签名完全匹配 free() 所以编译器不需要使用模板 自由的 .

        3
  •  2
  •   AnT stands with Russia    15 年前

    不能“替换”标准 malloc 使用这种技术。其他答案已经解释了这一点,因为您正在使用 签署 值作为参数 马洛克 调用时,模板化版本会“赢”标准版本,因为标准版本需要一个无符号参数。

    为了更好地说明这一点,我只想补充一点,如果你提供 unsigned int unsigned long 你的论点 马洛克 呼叫

    void *p1 = malloc(10u);
    void *p2 = malloc(10ul);
    

    你会注意到在其中一个调用中 马洛克 也不再“有效”,而是称为标准的,因为它更符合论点(前提是在您的平台上 size_t 定义为 无符号整型 无符号长 )

        4
  •  0
  •   Mark B    15 年前

    没有回答你问的问题,但你想做什么:

    如果它在您的系统上可用,您可以使用ld_preload来预加载一个.so库,您构建的库具有您的malloc和free版本。然后它们肯定会被调用,而不是标准版本。