空调风格的演员和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_castCObject*,但这不是你在这里做的。这里你试图将一个指针的引用转换为对另一个指针的引用。而这两种指针类型不具有继承关系。

我喜欢你的“好例子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

回到顶部