【发布时间】:2014-08-09 09:18:00
【问题描述】:
是否可以在 any std c++ 容器中维护派生类的知识,而无需使用指针,从容器中动态转换返回值?我知道我可以创建一个向量或某种基类类型的指针,并让它们保留它们的子类。但问题是我必须使用指针吗?
例子:
struct A {
int x = 0, y = 0, z = 0;
virtual void foo() { cout << "A" << endl; };
};
struct B : public A {
int a = 1, b = 1, c = 1;
virtual void foo() { cout << "B" << endl; };
};
int main() {
<SOMECONTAINER><A> a(2);
a[0] = A();
a[1] = B();
B * p;
B& n = dynamic_cast<B&>(a[1]); // Always throws?
p = dynamic_cast<B*>(&a[1]); // Always zero?
cout << p << endl;
}
【问题讨论】:
-
可以避免使用间接,例如具有变体数据类型;通过在每个元素旁边存储对象大小并在迭代时动态转到下一个元素(标准库容器不支持),也可以浪费更少的空间。
-
我强烈推荐观看Inheritance is the Base Class of Evil。 Sean Parent 描述了如何实现类似于
std::vector<Animal> v{Cat{}, Dog{}}; v[0].makeSound(); v[1].makeSound();打印Meow! Woof!的效果。所讨论的Cat和Dog类只需要一个名为makeSound的函数(成员或免费),该函数将该类作为参数。这些类不是从Animal派生的。 -
@ghostofstandardspast 如果我没记错的话,肖恩的方法仍然依赖于使用虚拟调度和动态分配。 (如果我的记忆不正确,请告诉我我是个白痴。)他只是使用持有者类将其隐藏为实现细节。这种方法非常好,但如果目标是避免动态分配,它就会失败。
-
您可以定义与 C++ 容器一起使用的(受限)变体数据类型。但是,您不能做的是将不同大小的对象放入标准库容器中。 (受限)变体数据类型通常以联合形式实现,因此具有它们可以包含的最大可能类型的大小。
-
@ChrisHayden,是的,仍然隐藏了虚函数的使用,但据我所知,OP 只是希望能够拥有一个“基类”对象的容器,而不是指针。