我需要定义一个可以接受可变数量参数的虚函数,问题是c样式省略号对非pod类型不起作用,我的内存量有限(2KB)所以我试图避免分配临时对象传递给函数,所有参数都是相同的类型(自定义共享指针),我也没有访问stl或boost。有没有一个c ++技巧可以让我用变量参数调用一个func?
答案 0 :(得分:4)
假设您的参数类型属于Arg
类,您可以尝试:
class ArgUser {
public:
// syntactic sugar:
void method() { // nullary
doMethod();
}
void method( const Arg & a1 ) { // unary
doMethod( &a1 );
}
void method( const Arg & a1, const Arg & a2 ) { // binary
doMethod( &a1, &a2 );
}
// and so on, until max arity
private:
// actual virtual function:
virtual void doMethod( const Arg * a1=0, const Arg * a2=0 /*etc, until max arity */ ) = 0;
};
此解决方案具有以下属性:
另一种解决方案(可能会或可能不会更有效)是:
class AltArgUser {
public:
// syntactic sugar:
void method() { // nullary
doMethod( 0, 0 );
}
void method( const Arg & a1 ) { // unary
doMethod( &&a1, 1 );
}
void method( const Arg & a1, const Arg & a2 ) { // binary
const Arg * args[] = { &a1, &a2 };
doMethod( args, 2 );
}
// and so on, until max arity
private:
// actual virtual function:
virtual void doMethod( const Arg * args[], size_t numArgs ) = 0;
};
要决定使用哪一个,您需要研究为特定平台上的每个方法生成的汇编程序。无论你选择什么,你都应该保留包装函数。
答案 1 :(得分:2)
定义函数以获取指向参数数组的指针和数组大小的参数。
此外,如果您不想对固定大小的数组进行硬编码,则可以使用alloca
在堆栈上分配存储,而不必担心跳转到堆或调用free
。< / p>
答案 2 :(得分:1)
指向共享指针的指针是POD,您是否可以更改原型以使用每个参数的内存位置?像这样(未经测试):
shared_ptr arg1;
shared_ptr arg2;
ClassWithVirtualFunction c;
c.yourVirtualFunction(&arg1, &arg2, NULL);
ClassWithVirtualFunction
{
virtual void yourVirtualFunction(shared_ptr* first, ...)
{
va_list marker;
va_start( marker, first );
shared_ptr* current=first;
while (current != NULL)
{
/* do stuff with *current */
current = va_arg( marker, shared_ptr* );
}
va_end(marker);
}
}
答案 3 :(得分:0)
您可以使用实际上更快的固定数组,并且比可变数量的参数占用更少的空间。因为可变数量的参数可以进行大量检查和安全。
mytype arr[3];
arr[0] = a;
// etc
myfunction(arr, 3);
答案 4 :(得分:0)
也许如果你已经拥有自己的自定义指针类型,你可以定义自己的基本链表类(毕竟这是C ++),最后一个“指向下一个指针”为NULL表示变量数字的结尾ARGS。
这样的事情:
class MyPointer
{
// Whatever you have/want
};
class MyArgs
{
static int nargs; // Static class variable for total number of args
MyPointer* data;
MyArgs* next;
public:
MyArgs(int nargs)
{
// Some funky constructor to create required number of args...
}
MyPointer* operator[](int at)
{
// Nice overloaded operator for you to get at data
}
};
class PlanToDoStuff
{
public:
virtual void foobar(MyArgs)=0;
};
class ActuallyDoStuff: public PlanToDoStuff
{
public:
void foobar(MyArgs)
{
// Do stuff with args...
}
};
int main()
{
MyArgs args(3);
ActuallyDoStuff dosomething;
dosomething.foobar(args);
}