比从基类转换为派生类更好的方法

Cyp*_*106 1 c++ class-design

我知道像这样的向下转换是行不通的.我需要一种可行的方法.这是我的问题:我从基类中得到了几个不同的派生类.我的第一个尝试是创建一个基类数组.程序必须选择(或多或少随机)不同的派生类.我曾尝试从基类转换到派生类,将它放在基类的数组中,但显然这不起作用.我真诚地希望采用另一种方法而不是简单地粘贴所有派生类的数组,因为可能会有相当多的派生类.有没有更好的方法来做到这一点,我只是在脑力训练?

如果您需要代码示例或更多信息,请告诉我.这对我来说都是有意义的,但现在已经很晚了,对其他人来说可能没有意义.

伙计们,非常感谢任何帮助.

Joh*_*itb 13

不明白你的意思.听起来像是按值存储对象,而你有一个数组Base.这不起作用,因为只要您分配Derived,该对象将被转换为Base,并且对象的Derived部分被切掉.但我想你想要一个基数指针数组:

Base * bases[NUM_ITEMS];
for(int i=0; i<NUM_ITEMS; i++) {
    int r = get_random_integer();
    if(r == 0)
        bases[i] = new Derived1;
    else if(r == 1)
        bases[i] = new Derived2;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果你曾经使用过指针,你就会知道管理它们很麻烦,特别是传递并且不会丢失它们,因为你需要调用delete来释放内存并调用对象的析构函数.您可以使用shared_ptr,它将为您管理:

shared_ptr<Base> bases[NUM_ITEMS];
for(int i=0; i<NUM_ITEMS; i++) {
    int r = get_random_integer();
    if(r == 0)
        bases[i].reset(new Derived1);
    else if(r == 1)
        bases[i].reset(new Derived2);
    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以传递bases[x]给另一个shared_ptr,它会注意到您有多个引用 - 如果对象的最后一个引用超出范围,它将自动调用.理想情况下,您还可以用std :: vector替换原始数组:

std::vector< shared_ptr<Base> > bases;
for(int i=0; i<NUM_ITEMS; i++) {
    int r = get_random_integer();
    if(r == 0)
        bases.push_back(shared_ptr<Base>(new Derived1));
    else if(r == 1)
        bases.push_back(shared_ptr<Base>(new Derived2));
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后你可以传递向量,不要丢失它的大小,你可以根据需要动态添加项目.使用获取向量的大小bases.size().在shared_ptr 这里阅读.

只有在绝对必要时才能从Base类转换为Derived类.通常,你想使用一种叫做的技术polymorphism,这意味着你在基指针上调用一个函数,但它实际上会调用一个在派生类中定义的函数,具有相同的签名(名称和参数是相同的类型)并且被称为到override它.阅读维基百科上关于它的文章.如果你真的需要强制转换,你可以这样做一个原始指针:

Derived1 * d = &dynamic_cast<Derived1&>(*bases[x]);
Run Code Online (Sandbox Code Playgroud)

使用dynamic_cast可以确保,当您转换为错误的类型时(即,您投射的类型不是创建并分配给基指针的类型),您将获得操作员抛出的异常.对于shared_ptr案例,也有一些方法:

shared_ptr<Derived1> d = dynamic_pointer_cast<Derived1>(bases[x]);
if(d) {
    // conversion successful, it pointed to a derived. d and bases[x] point still 
    // to the same object, thus share it. 
}
Run Code Online (Sandbox Code Playgroud)


Leo*_*Hat 10

在大多数情况下,从基类转换为派生类是一种糟糕的代码味道.

通过使用虚拟方法,多态性是一种更好的方法.

调用代码应使用基类指针调用方法,允许将其分派到派生类中的相应实现.

我知道这是一个相当通用的答案,但如果没有一些代码片段作为示例,很难在您的情况下推荐更具体的答案.