三元运算符将类扩展宏应用于两个操作数

时间:2016-03-19 04:00:53

标签: c++ class visual-c++ macros ternary-operator

我使用的是Microsoft Visual C ++ 2010和Windows 7。

我有DataDecoder类来解码一些数据。这是:

template< typename T >
class DataDecoder
{

private:

    T lpData;

public:

    DataDecoder() { lpData = NULL; }
    DataDecoder( T lpSource ) { lpData = (T)DecodeStaticData(lpSource); }
    ~DataDecoder() { if(lpData) free(lpData); }
    operator T() { return lpData; }
};

这个课程很完美。我也有这个宏:

#define _STR_A(x) DataDecoder<char*>(x)

它也很完美。但是我的代码还有另一种结构:

LPVOID lpAdditionalData = NULL;
LPSTR lpTemp = lpAdditionalData ? _STR_A("SOMEDATA") : NULL;

此时奇怪的事情开始发生。首先,我在DecodeStaticData()中获取NULL参数。但事实并非如此:_STR_A()仅适用于有效参数。然后我决定看看反汇编:

0011843A  cmp         dword ptr [lpAdditionalData],0  
00118441  je          WinMain+172h (118462h)  
00118443  push        offset string "SOMEDATA" (124068h)  
00118448  lea         ecx,[ebp-0C2Ch]  
0011844E  call        DataDecoder<char *>::DataDecoder<char *> (117770h)  
00118453  or          dword ptr [ebp-0C14h],1  
0011845A  mov         dword ptr [ebp-0C34h],eax  
00118460  jmp         WinMain+18Ch (11847Ch)  
00118462  push        0  
00118464  lea         ecx,[ebp-0C28h]  
0011846A  call        DataDecoder<char *>::DataDecoder<char *> (117770h)

如您所见,类构造函数在两种情况下都被调用,对于“SOMEDATA”和NULL也是如此!

这是正确的行为吗?我怎么处理这个?

更新:我打开了预处理文件,这就是我所看到的:

LPSTR lpTemp = lpAdditionalData ? DataDecoder<char*>("SOMEDATA") : 0;

因此,它不是预处理器问题。

1 个答案:

答案 0 :(得分:3)

与任何表达式一样,涉及条件运算符的表达式必须具有类型。表达式c ? a : b不能奇怪地具有在运行时更改的类型,具体取决于c的值 - 有时a的类型,b其他类型倍。相反,如果ab属于不同的类型,则会有一些复杂的规则决定整个表达式的最终类型,方法是尝试将其强制转换为另一种类型。

在您的情况下,DataDecoder<char*>(x)无法强制转换为NULL的类型,但NULL可以通过用户定义强制转换为DataDecoder<char*>转换DataDecoder<char*>(NULL)。这就是你观察到的。