在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一样的信号和插槽系统。虽然我不知道如何自己做这样的事情。
感谢您的阅读;我希望你有一些建议。
答案 0 :(得分:5)
好吧,如果你认识到JavaScript函数的哪个特性使这成为可能,那么在C ++中做同样的事情并不难。在JavaScript函数中也有闭包,C ++中的常规函数没有。但是C ++ lambda属于闭包类型。如果一个人将bunny
定义为既可以包含闭包类型的对象又可以重新分配的东西,那么你就可以了。{/ p>
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();
答案 1 :(得分:1)
你可以使用仿函数。
#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;
}
答案 2 :(得分:1)
假设目标是允许调用代码扩展程序的功能,超出初始代码提供的功能,我可能会使用一个用户可更新的仿函数对象数组,如下所示:
#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;
}
答案 3 :(得分: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()
,请将其删除。