C++ 将派生子类转换为另一个派生子类

问题描述

所以我在这里试图实现的是将一个派生的子类转换为从同一子类派生的另一个子类。到目前为止,它看起来似乎不可能真正完成,但我仍然相信。

我的示例代码是:

#include <iostream>
#include <vector>

class BaseClass
{
public:
    virtual void printFunction() = 0;
};

class printOne : public BaseClass
{
public:
    void printFunction() override
    {
        std::cout << "One\n";
    }
};

class printTwo : public BaseClass
{
public:
    void printFunction() override
    {
        std::cout << "Two\n";
    }
};

int main()
{
    std::vector<BaseClass *> baseClassvector;

    printOne * one = new printOne;
    baseClassvector.push_back(one);

    printTwo * two = new printTwo;
    baseClassvector.push_back(two);

}

所以我想在这里用这个向量实际做的是我想将索引零上的“一”对象更改为“二”对象。现在这可以通过代码来完成

delete baseClassvector[0];

printTwo * two = new printTwo;
baseClassvector[0] = two;

但是据我所知,这是非常昂贵的,特别是如果它必须在运行时完成。我想知道是否还有其他方法可以做到这一点,或者与其他替代方案相比,成本是否值得。

提前致谢!

解决方法

对于问题中的简化示例,使用更简单的 std::variant 并且完全避免使用基类:

class printOne
{
public:
    void printFunction() const
    {
        std::cout << "One\n";
    }
};

class printTwo
{
public:
    void printFunction() const
    {
        std::cout << "Two\n";
    }
};

using printEither = std::variant<printOne,printTwo>;

void printFunction(const printEither& e)
{
    std::visit([](auto& p) { p.printFunction(); },e);
}

int main()
{
    std::vector<printEither> eitherVector;

    printOne one;
    eitherVector.push_back(one);

    printTwo two;
    eitherVector.push_back(two);

    eitherVector[0] = two;

    for (auto& e: eitherVector)
        printFunction(e);
}

在 C++ 中为有效不相关的类型重新使用分配是正确编写的痛苦。进行分配更容易也更可取。

,

从技术上讲,可以将对象“重建”为不同类型,但以下内容应仅作为概念证明,而不是设计或实践的建议。首先要付出的代价是放弃 new/delete 的便利性,以便手动管理展示位置与 malloc/free 一起使用的新的显式析构函数。

const size_t sz = max(sizeof(printOne),sizeof(printTwo));

BaseClass *either = (BaseClass *)malloc(sz);       // allocate memory for objects

new(either) printOne();                            // construct printOne object
printOne *one = dynamic_cast<printOne *>(either);  // ... use printOne object
one->~printOne();                                  // destruct printOne object

new(either) printTwo();                            // construct printTwo object
printTwo *two = dynamic_cast<printTwo *>(either);  // ... use printTwo object
two->~printTwo();                                  // destruct printTwo object

free(either);                                      // free memory used by objects