作者:kevin_xi | 来源:互联网 | 2023-10-11 09:43
出于好奇,我想我会尝试编写一个基本的C类,模仿C#的多个委托模式.下面的代码主要完成了这项工作,几乎所有类型安全都遭受了令人讨厌的牺牲,但是必须使用初始的伪参数来设置va_list
出于好奇,我想我会尝试编写一个基本的C类,模仿C#的多个委托模式.下面的代码主要完成了这项工作,几乎所有类型安全都遭受了令人讨厌的牺牲,但是必须使用初始的伪参数来设置va_list似乎确实有些偏差.有没有办法在没有这个的情况下使用va_list?
我确实知道有很多方法可以用(例如)boost来做到这一点,但是我的目标是使用标准库的简单方法.
#include
#include
#include
#include
#include
using namespace std;
class CDelegate
{
public:
virtual bool operator()(va_list params) = 0;
};
class CMultipleDelegateCaller
{
public:
typedef vector CDelegateVector;
CMultipleDelegateCaller& operator+=(CDelegate &rDelegate)
{
m_apDelegates.push_back(&rDelegate);
return (*this);
}
CMultipleDelegateCaller& operator-=(CDelegate &rDelegate)
{
CDelegateVector::iterator iter =
find(m_apDelegates.begin(), m_apDelegates.end(), &rDelegate);
if (m_apDelegates.end() != iter) m_apDelegates.erase(iter);
return (*this);
}
bool Call(int iDummy, ...)
{
va_list params;
CDelegate* pDelegate;
CDelegateVector::iterator iter;
for (iter = m_apDelegates.begin(); iter != m_apDelegates.end(); ++iter)
{
pDelegate = *iter;
va_start(params, iDummy);
if (!(*pDelegate)(params)) return false;
va_end(params);
}
return true;
}
private:
CDelegateVector m_apDelegates;
};
class CTestDelegate:
public CDelegate
{
public:
CTestDelegate():m_iId(++s_iCount) {}
virtual bool operator()(va_list params)
{
int iIntParam = va_arg(params, int);
char* szCharPtrParam = va_arg(params, char*);
string* psStringParam = va_arg(params, string*);
cout< < < <<*psStringParam<<"}"< return true;
}
int m_iId;
static int s_iCount;
};
int CTestDelegate::s_iCount = 0;
int main(int argc, char* argv[])
{
CMultipleDelegateCaller cDelegateCaller;
CTestDelegate cTestDelegate1;
CTestDelegate cTestDelegate2;
cout<<"--------------------"< cDelegateCaller += cTestDelegate1;
cDelegateCaller += cTestDelegate2;
string sString("World");
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"< cDelegateCaller -= cTestDelegate1;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"< cDelegateCaller -= cTestDelegate2;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"< cin>>sString;
return 0;
}
解决方法:
C中带省略号的函数仅用于与C的兼容.使用C我将在Call函数中返回临时助手对象,并添加模板运算符%以传递可变数量的参数.要按以下方式使用它:
cDelegateCaller.Call() % 2 % "Hello" % sString; // dummy argument isn't required
至于你的问题,标准要求在任何访问未命名参数之前调用va_start.并且va_start需要第二个参数,它是函数定义中变量参数列表中最右边参数的标识符.