是否有一种可移植的方法来定义可替换的函数/变量/常量?

时间:2015-10-21 12:32:47

标签: c++ c portability

通过可替换函数,我的意思是像C ++中的newdelete运算符,如果提供了用户提供的定义,它们将被替换。

对于除运算符newdelete(在C / C ++中)之外的其他情况,是否有一种合理的可移植方式在库中实现此目的?或者是否需要为每个实现单独解决这个问题?

对于一个具体的例子,我们假设该库包含:

int the_answer(void) {
    return 42;
}

然后使用它的程序想要覆盖它:

int the_answer(void) {
    return 43;
}

int main() {
    printf("The answer is %d\n", the_answer());
}

它应该导致它打印"答案是43" (但如果评论出the_answer的最后一个定义,它会写出#34;答案是42")。

实际用例是通过覆盖默认行为的数据来自定义库的行为。

3 个答案:

答案 0 :(得分:3)

在C ++中,您可以使用模板的优先级低于不需要隐式转换/构造参数的实现的事实。

// library function
template <class = void>
int the_answer() { return 42; }

// optional override
int the_answer() { return 43; }

请注意,定义顺序并不重要,模板总是丢失。

答案 1 :(得分:0)

当然,对于除运营商之外的任何事情。请注意,C没有运算符重载,因此您的问题被错误标记。

对于函数/变量/常量,您可以定义一个宏来执行预期的操作。当重载(或者更换),#undef宏并定义一个新宏。适用于C或C ++,虽然非常危险。

在C中,不能选择重载或替换功能。要么必须使用预处理器,如上所述,要么实际编辑生成的二进制文件以使用您的函数。

在C ++中,您可以创建一个使用虚函数的多态类,覆盖以前的定义。这将是覆盖库本身操作的最简单的解决方案。

在任何一种语言中,如果不重新编译,就很难改变变量的类型或常量的值。

答案 2 :(得分:-2)

  1. 全局函数指针?
  2. Functor重载?
  3. 全局函数指针

    假设您的图书馆以这种方式定义doCoffee()函数:

    void doCoffee_impl() { /* ... */ }
    void (doCoffee*)(void) = doCoffee_impl;
    

    然后,您的图书馆用户可以通过重新影响全局变量来替换doCoffee的行为。

    Functor重载

    但是,嘿!你正在编写C ++。为什么不使用虚拟operator()

    struct Brewer
    {
        virtual operator()() { /* ... */ }
    } brewer;
    brewer *doCoffee = &brewer;
    

    您的用户可能会超载:

    struct UserBrewer : public Brewer
    {
        virtual operator()() { /* ... */ }
    } userBrewer;
    doCoffee = &userBrewer;
    

    让读者:在源头中声明变量static或者定义extern,并在提供的编译单元中定义变量。