空调风格的演员和C++的static_cast到指针
的参考这是不是C++ 11空调风格的演员和C++的static_cast到指针
我感兴趣的是微软的 CMapStringToOb::GetNextAssoc,第3参数,它具有以下定义:
void GetNextAssoc( POSITION& rNextPosition,
CString& rKey,
CObject*& rValue
) const;
然后我有以下简单的测试代码:两个好例子和一个编译器错误的例子。
class CMyObject : public CObject //in order to use CMapStringToOb {
public:
CMyObject(CString name_)
:name(name_)
{
}
void SayHello()
{
TRACE(_T("hello") + name);
}
CString name;
};
void main()
{
CMapStringToOb myMap;
myMap.SetAt(_T("a"), new CMyObject(_T("aaa")));
myMap.SetAt(_T("b"), new CMyObject(_T("bbb")));
myMap.SetAt(_T("c"), new CMyObject(_T("ccc")));
//good case 1
POSITION pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CMyObject* pMine = NULL;
myMap.GetNextAssoc(pos, s, (CObject*&)pMine);
if(pMine)
{
pMine->SayHello();
}
}
//good case 2
pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CObject* pObject = NULL;
myMap.GetNextAssoc(pos, s, pObject);
if(pObject)
{
CMyObject* pMine = static_cast<CMyObject*>(pObject);
pMine->SayHello();
}
}
//bad case:
//can not compile
// error C2440: 'static_cast' : cannot convert from 'CMyObject *' to 'CObject *&'
// static_cast and safe_cast to reference can only be used for valid initializations or for lvalue casts between related classes
pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CMyObject* pMine = NULL;
myMap.GetNextAssoc(pos, s, static_cast<CObject*&>(pMine)); //compile error
if(pMine)
{
pMine->SayHello();
}
}
}
所有我试图做的是找到一种正确的方式来取代C风格铸造到C++风格铸造在这种情况下。
从this阅读,它提到:
Ç管型是使用(类型)的对象或类型(对象)的类型转换。投 A C式被定义为其中第一个成功以下的:
const_cast
static_cast (though ignoring access restrictions)
static_cast (see above), then const_cast
reinterpret_cast
reinterpret_cast, then const_cast
Q1的:以上列表中缺少任何东西(例如,用于右值)?
Q2:在这种情况下,将C风格转换为C++风格转换的正确方法是什么? (好的情况2有效,但是,有没有更简洁的一个?)
问题3:C风格如何为rValue执行操作? (换句话说,请解释为什么好的情况1工作)
回答:
您不能static_cast
引用(或指针)到“不相关的类型”之间。虽然你可以从CMyObject*
static_cast
到CObject*
,但这不是你在这里做的。这里你试图将一个指针的引用转换为对另一个指针的引用。而这两种指针类型不具有继承关系。
我喜欢你的“好例子2”代码 - 我就是这样运行的。
有关指针类型的非关联的详细信息,请看这里:static_cast and reference to pointers
回答:
正确的方法编写的代码是使用std::map<>
。即使您坚持主要保留现有代码,也可以考虑修复GetNextAssoc()
的界面以返回指针。为了做到这一点,你可以简单地添加函数的重载:
CObject* GetNextAssoc( POSITION& rNextPosition,
CString& rKey,
) const {
CObject* res = 0;
GetNextAssoc(rNextPosition, rKey, res);
return res;
}
更有甚者,你可以模板功能进行转换为目标类型存在。此外,您可以使用dynamic_cast
,因为正式使用,容器商店CObjects
,它们可能有各种不同的类型。
现在,为什么我会部分忽略你的问题?原因是MFC不遵循现代编码风格,在某些情况下,他们只是做一些令人不悦的事情。这种行为有很多理由,但最重要的是年龄(不知道更好,没有适当的模板支持)和兼容性问题(现在无法改变)。这不是重复这些错误的理由。
回答:
约翰Zwinck的启发,我会从不同的角度:
static_cast<CObject*>(pMine)
将成功因为类型 “CMyObject” 从类型 “CObject的” 一概而论;实际上,这是隐含的;
static_cast<CMyObject*>(pObject)
将成功因为类型 “CMyObject” 从类型 “CObject的” 一概而论;
static_cast<CObject**>(&pMine)
将失败因为类型 “CMyObject *” 不从类型概括 “CObject的*”;
reinterpret_cast<CObject**>(&pMine)
将在因为 “reinterpret_cast的” 编译时成功; 运行时间怎么样?
让我们把可能出现的新的实现的假设:
void CMapStringToOb::GetNextAssoc( POSITION& rNextPosition,
CString& rKey,
CObject** ppValue)
{
*ppValue = (the pointer at the current position, point to an instance of "CMyObject");
}
所以通过调用这个函数:
GetNextAssoc(pos, s, reinterpret_cast<CObject**>(&pMine))
的结果是,“pMine”指向的实例“ CMyObject“;
因此运行时间是SAFE。
然而,如果把它插入由键值(注:CYourObject无期广义关系CMyObject)
myMap.SetAt(_T("a"), new CYourObject(_T("aaa")));
,并把它弄出来的
GetNextAssoc(pos, s, reinterpret_cast<CObject**>(&pMine));
编译的时候还是会成功,但是,pMine现在指向“CYourObject”,它将在运行时处为未定义的行为。 (虽然static_cast具有相同的问题,但)
以上是 空调风格的演员和C++的static_cast到指针 的全部内容, 来源链接: utcz.com/qa/257478.html