在 C++ 中修改现有函数的任何技术或技巧?

Any techniques or tricks to modifying existing functions in C++?

在 JavaScript 内,您可以完成这样的事情:

function bunny() { alert("The bunny jumped."); }

var oldBunny = bunny;
function bunny() {
  oldBunny();
  alert("The bunny also ran.");
}

bunny(); // The bunny Jumped. The bunny also ran.

正如你所看到的,旧的 "bunny" 函数通过复制到一个变量来附加代码,然后用相同的名称重新创建函数。原函数拷贝运行,新代码也运行

我希望在 C++ 中复制类似的机制。

现在,在您崩溃并开始解释静态语言和动态语言之间的区别之前,我明白了。我不是在寻找与所提供的相同的东西,但我确实想要类似的东西。

此外,我这样做并不是为了修改现有代码;我希望格式化我自己的源代码,以允许其他用户利用这种机制。

我的第一个想法可能是在代码中设置各种宏,以后可以由其他文件修改。

另一个想法是创建一个类似于 QT 的信号和插槽系统。虽然我自己也不知道怎么做。

感谢您的阅读;希望大家多提建议。

你可以使用仿函数。

#include <iostream>
#include <string>

class Base
{
public:
    virtual std::string operator ()()
    {
        return "Base call";
    }

    virtual ~Base() {}
};

class Derived : public Base
{
public:
    virtual std::string operator()()
    {
        return "Wrapper: " + Base::operator()();
    }
};

int main()
{
    Base* pFun = new Base;
    std::cout << "Now check Base: " << (*pFun)() << std::endl;

    delete pFun;
    pFun = new Derived;
    std::cout << "Now check Derived: " << (*pFun)() << std::endl;

    return 0;
}
void bunny()
{
    cout << "The bunny jumped." << endl;
}

void oldBunny()
{
    bunny();
}

void newBunny()
{
    bunny();
    cout << "The bunny also ran." << endl;
}

#define bunny newBunny

int main()
{
    bunny();
    return 0;
}

如果不需要oldBunny(),直接删除即可。

假设目标是允许调用代码扩展程序的功能,超出初始代码提供的功能,我可能会使用用户可更新的仿函数对象数组,如下所示:

#include <iostream>
#include <memory>

class Function
{
public:
   virtual void Call() = 0;
};
typedef std::shared_ptr<Function> FunctionSharedPointer;

class OldBunny : public Function
{
public:
   virtual void Call()
   {
      std::cout << "The bunny jumped." << std::endl;
   }
};

class NewBunny : public Function
{
public:
   NewBunny(FunctionSharedPointer oldFunction) : _oldFunction(oldFunction) {/* empty */}

   virtual void Call()
   {
      _oldFunction->Call();
      std::cout << "The bunny also ran." << std::endl;
   }

private:
   FunctionSharedPointer _oldFunction;
};

enum {
   FUNCTION_BUNNY,
   // other functions could be declared here later...
   NUM_FUNCTIONS
};

// Our table of functions that the user can Call() if he wants to
static FunctionSharedPointer _functionTable[NUM_FUNCTIONS];

// Wrapper function, just to keep users from accessing our table directly,
// in case we ever want to change it to something else
void CallFunction(int whichFunction)
{
   _functionTable[whichFunction]->Call();
}

// Another wrapper function
void SetFunction(int whichFunction, FunctionSharedPointer newFunctionDefinition)
{
   _functionTable[whichFunction] = newFunctionDefinition;
}

// And another
FunctionSharedPointer GetFunction(int whichFunction)
{
   return _functionTable[whichFunction];
}

int main(int argc, char ** argv)
{
   // Our default function values get set here
   SetFunction(FUNCTION_BUNNY, std::make_shared<OldBunny>());

   std::cout << "before:" << std::endl;
   CallFunction(FUNCTION_BUNNY);

   // Now let's update an entry in our function table to do something different!
   FunctionSharedPointer op = GetFunction(FUNCTION_BUNNY);
   FunctionSharedPointer np = std::make_shared<NewBunny>(op);
   SetFunction(FUNCTION_BUNNY, np);

   std::cout << "after:" << std::endl;
   CallFunction(FUNCTION_BUNNY);

   return 0;
}

好吧,如果您认识到 JavaScript 函数的哪个特性使这成为可能,那么在 C++ 中做同样的事情就不难了。在 JavaScript 中,函数也有闭包,这是 C++ 中的常规函数​​所没有的。但是 C++ lambda 是闭包类型的。如果将 bunny 定义为既可以容纳闭包类型的对象又可以重新分配的对象,那么您就已经准备好了。

C++ 标准库为此提供了一个不错的默认选择,形式为 std::function。我们可以将您原来的 JavaScript 重写如下:

std::function<void()> bunny = [] {
  std::cout << "The bunny jumped.\n";
};

auto oldBunny = std::move(bunny);
bunny = [oldBunny] {
  oldBunny();
  std::cout << "The bunny also ran.\n";
};

bunny();