C ++确实reinterpret_cast总是返回结果?

时间:2017-07-11 20:38:09

标签: c++ reinterpret-cast

我有两个类,A和B. A是B的父类,我有一个函数,它接受指向类型A的类的指针,检查它是否也是类型B,如果是将调用另一个函数,该函数接受指向类型B的类的指针。 当函数调用另一个函数时,我提供reinterpret_cast(a)作为参数。如果这看起来很模糊,这里有一个代码示例:

void abc(A * a) {
  if (a->IsA("B")) { //please dont worry much about this line,
                     //my real concern is the reinterpret_cast
    def(reinterpret_cast<B *>(a));
  };
};

所以现在你知道我是如何调用&#34; def&#34;,我想知道reinterpret_cast是否实际上返回了一个类型B的指针作为参数发送到def。 我将不胜感激任何帮助。 感谢

5 个答案:

答案 0 :(得分:5)

reinterpret_cast会一直做你说的 - 它是一个雪橇。你可以做到

IEnumerable<ListingStat> GetListingStats(int inCompanyID, int inMonth, int inYear);


public IEnumerable<ListingStat> GetListingStats(int inCompanyID, int inMonth, int inYear)
{
    //var x = document.getElementById("sortSelect").value;

    // there's probably a way to make ef do this query in an efficient manner.. but, there aren't nice keys between listingstats and makemodel stats, and I'm not going to create them for the sake of ef
    var theSQL = "select d.DatePK, ls.*, " +
                 "mm.Make as MM_Make, mm.Model as MM_Model, mm.ListingsThatWereActive as MM_ListingCount, mm.MedianPriceExcludeZero as MM_MedianPrice, mm.PopularityRank as MM_PopularityRank, " +
                 "mm.PopularityMaxRank as MM_PopularityMaxRank, mm.AverageFavorites as MM_Favorites, mm.AverageSearchImpressions as MM_SearchImpressions, mm.AverageBuyerInquiries as MM_BuyerInquiries, mm.AveragePhoneInquiries as MM_PhoneInquiries, mm.AverageListingViews as MM_ListingViews, " +
                 "ymm.SupplyDemandIntegerPercentile as YMM_SupplyDemandPercentile, ymm.TotalListingViews as YMM_TotalListingViews " +
                 "from " +
                 "PerformanceDataMart.Dates d " +
                 "left outer join PerformanceDataMart.ListingStats ls on ls.DateFK = d.DatePK and ls.CompanyId = :CompanyID " +
                 "left outer join PerformanceDataMart.MakeModelStats mm on mm.DateFK = d.DatePK and mm.Make = ls.Make and mm.Model = ls.Model and mm.Year is null " +
                 "left outer join PerformanceDataMart.MakeModelStats ymm on ymm.DateFK = d.DatePK and ymm.Make = ls.Make and ymm.Model = ls.Model and ymm.Year = ls.Year " +
                 "where d.Month = :Month and d.Year = :Year";

    var theDB = new CCDB();

    List<ListingStat> theList = new List<ListingStat>();

    using (IDataReader aDR = theDB.OpenDataReader(theSQL, inCompanyID, inMonth, inYear))
    {
        while(aDR.Read())
        {
            ListingStat theListingStat = new ListingStat();
            theList.Add(theListingStat);

            theListingStat.ListingId = As.Integer(aDR["ListingId"]);
            theListingStat.Year = As.Integer(aDR["Year"]);
            theListingStat.Make = As.String(aDR["MM_Make"]);
            if (theListingStat.Make == "")          // shouldn't happen, but just in case
                theListingStat.Make = As.String(aDR["Make"]);

            theListingStat.Model = As.String(aDR["MM_Model"]);
            if (theListingStat.Model == "")             // shouldn't happen, but just in case
                theListingStat.Model = As.String(aDR["Model"]);
        }
    }

    return theList;
}

def(reinterpret_cast<B *>(42));

它将始终返回指向正确类型的指针。它假设你知道你在做什么

答案 1 :(得分:3)

你会有一个B*类型的指针,但reinterpret_cast并不是很好。

如果你确定类型是B,请使用static_cast,如果没有,请使用dynamic_cast并测试指针(如果dynamic_cast失败,则返回nullptr

请参阅https://stackoverflow.com/a/332086/5303336

答案 2 :(得分:2)

reinterpret_cast是类型系统损坏的结果。它的行为假定存在诸如

之类的联合
 union { 
     TypeA anA;
     TypeB aB;
 } a;

所以

 reinterpret_cast< B* >( a );

假设a是指向成员anA的指针,然后可以传递aB地址。

如果类型是同一类层次结构的一部分,则static_cast&lt;&gt;将允许您在编译时找出是否有足够的信息来执行演员表。这通常是BA的基类(单独或乘法)。

如果static_cast的信息不足,则可能会获得dynamic_cast&lt;&gt;上班。这种情况是B类型以某种方式从A派生而来。

请务必注意,dynamic_cast<B*>( a )static_cast< B*>( a )在成功时可能不会产生相同的地址。

这是因为当乘法继承时,辅助继承会在对象中创建多个类和vtable。发生这种情况时,static_cast,dynamic_cast调整对象的基址以找到正确的嵌入式类基址。

dynamic_cast和static_cast可能会更改地址,这是不鼓励reinterpret_cast的原因。它可能会产生一个不符合你想要的价值。

答案 3 :(得分:1)

重新解释强制转换将始终返回指针。它实际上可能指向B类型的对象,它可能不是一个有效的指针。

如果B有多个基类,并且A不是第一个基类,则重新解释强制转换将执行错误操作并且无法对指针执行必要的调整。

对于您的用例,您应该使用静态强制转换,其优点是编译器将检查B是否实际上是从A派生并执行任何所需的调整。额外检查不会产生运行时开销,但如果对象实际上不是B类,并且程序将随意失败,则不会发出警告。

答案 4 :(得分:1)

正如其他人所说,reinterpret_cast是错误的解决方案,请改用dynamic_cast

void abc(A * a) {
    B *b = dynamic_cast<B*>(a);
    if (b) {
        def(b);
    }
}