派生**到基地**

时间:2016-10-07 12:38:38

标签: c++ arrays inheritance casting

请考虑以下代码:

#include <iostream>

using namespace std;

class Base
{
public:
    int foo;
};

class Derived : public Base
{
public:
    float bar;
};

int main()
{
    Base** baseArr = new Base*[30];

    for (int i=0; i<30; i++)
    {
        Derived* derived = new Derived();
        derived->foo = i;
        derived->bar = i * 2.5;
        baseArr[i] = derived;
    }

    //Notice this!
    Derived** derivedArr = (Derived**)(baseArr);

    for (int i=0; i<30; i++)
        cout << "My Base " << i << ": " << derivedArr[i]->foo << ", " << derivedArr[i]->bar << endl;

    return 0;
}

将此数组用于数组转换是否安全?整个程序的指针大小相同,所以听起来我不会得到任何填充错误。但是,我知道正确的方法是遍历每个元素并单独转换它。

但是,我试图利用这种类型的强制转换通过使用非泛型私有函数返回数组将我的模板公共函数实现移动到.cpp文件,所以我可以确定我的Base数组只包含具体的Derived指针。

private:
    Base** Find(function<bool(Base*)> Predicate, int& N); //Implemented in .CPP

public:
    template <class T> T** FindByType(int &N) //T is derived from Base
    {
        //Safe?
        return (T**)(Find(
            [](Base* b)->bool { return typeid(T) == typeid(b); },
            N));
    };

当然,这只是一个简化的例子。在这种情况下,我有很多理由使用RTTI。 N用于控制数组大小。

我想知道这种不安全的强制转换是否会因多重继承而失败,例如Derived类也会继承OtherBase而我想投靠OtherBase**,我d也想知道我是否有机会通过这个演员表达到未定义的行为,或者如果我决定使用这个结构,我可能会遇到任何潜在的问题。

2 个答案:

答案 0 :(得分:2)

不,这不安全。

指向Derived的指针与指向Base的指针不同。指向Derived的指针可以转换为指向Base的指针,但最终结果是不同的指针。

因为指向Derived的指针与指向Base的指针不同,指向Derived的指针也不是指向指针的指针。指向Base的指针。

答案 1 :(得分:1)

不,这是不安全的。

  

如果某个程序试图通过以下某种类型之外的 glvalue 访问对象的存储值,则行为未定义:

     
      
  • 对象的动态类型,
  •   
  • 对象的动态类型的cv限定版本,
  •   
  • 与对象的动态类型相似的类型(如4.4中所定义),
  •   
  • 与对象的动态类型对应的有符号或无符号类型的类型
  •   
  • 与对象的动态类型的cv限定版本对应的有符号或无符号类型的类型,
  •   
  • 聚合或联合类型,其元素或非静态数据成员中包含上述类型之一(包括递归地,元素或非静态数据成员子集合或包含的联合>,
  •   
  • 一种类型,它是对象动态类型的(可能是cv限定的)基类类型,
  •   
  • charunsigned char类型。
  •   

Ben

无耻地被盗

在将Base**转换为Derived**的情况下,这些情况都不属实。

相关问题