【发布时间】:2021-04-01 16:45:04
【问题描述】:
所以我在这里想要实现的是将派生的子类转换为从同一子类派生的另一个子类。到目前为止,它看起来似乎不可能真正做到,但我仍然相信。
我的示例代码是:
#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;
但据我所知,这是非常昂贵的,尤其是如果它必须在运行时完成。我想知道是否有其他方法可以做到这一点,或者与其他替代方案相比,成本是否值得。
提前致谢!
【问题讨论】:
-
如果您的类层次结构负担得起,您可以使用CRTP,也称为静态多态性。不会有任何运行时开销,但会限制您构建类层次结构的方式,如前所述。 “但是据我所知,这是非常昂贵的......” 也许比你想象的要少。测量,尝试消除完成动态转换的瓶颈,然后再次测量。
-
struct base {}会派上用场 -
请注意,要使
delete baseClassVector[0]正常工作,BaseClass必须具有虚拟析构函数。如果通过指向基类型的指针删除派生类型的对象,并且该基类型没有虚拟析构函数,则行为未定义。你的例子它可能“工作”得很好。这是未定义行为的一个隐蔽属性:您的代码有时不会显示任何症状,因此您不会注意到问题。然后你做了一个小的改变,事情就开始爆炸了。 -
在技术上可以转换指针。这种方法的“成本”可能是不可接受的 - 对象的后续使用(由指针指向)会产生未定义的行为。
-
@πάνταῥεῖ 指向基类型的指针向量表明,这里需要真正的动态多态性。
标签: c++ polymorphism derived-class