c++中的多态性,父类的载体中的类型丢失
polymorphism in c++, loss of type in vector of parent class
我有一个类a,它是类B和C的父类。还有一个类X,它是Y和Z的父类。
class A {};
class B : public A {};
class C : public A {};
class X
{
void foo(A) { std:: cout << "A"; }
};
class Y : public X
{
void foo(B) {std::cout << "B"; }
};
class Z : public X
{
void foo(c) {std<<cout <<"C"; }
};
int main()
{
B b;
C c;
Y y;
Z z;
y.foo(b);//prints B // b is a B, and Y::foo takes a B, hence print B
y.foo(c);//prints A // mismatch between types, fall back and print A
z.foo(b);//prints A // mismatch between types, fall back and print A
z.foo(c);//prints C // c is a C, and Y::foo takes a C, hence print C
std::vector<A> v;
v.push_back(b);
v.push_back(c);
//In this loop, it always prints A, but *this is what I want to change*
for (size_t i = 0; i < v.size(); ++i)
{
z.foo(v.at(i));
y.foo(v.at(i));
}
}
是否可以让项目打印与硬编码调用相同的结果?这意味着我会把它们当作它们的原始类型,而不是它的父类型?或者一旦我把它们放在a的向量中,它们将永远是a型的?
您看到的是对象切片
您将派生类的对象存储在一个向量中,该向量本应存储基类的对象,这导致对象切片,并且存储的对象的派生类特定成员被切片,因此存储在向量中的对象仅充当基类的对象。
解决方案:
您应该将指向基类对象的指针存储在向量中:
vector<X*>
通过存储一个指向基类的指针,就不会有切片,并且通过使函数virtual
也可以实现所需的多态行为
正确的方法是使用合适的智能指针,而不是在矢量中存储原始指针。这将确保您不必手动管理内存,RAII将自动为您管理内存。
这被称为切片。当您将元素push_back
复制到std::vector<A>
中时,它基本上将elements
复制到新构建的A
实例中。因此,来自派生类的对象的部分of将丢失("切片")。
为了避免切片,您需要使用一个存储指针而不是元素的容器,因此您应该使用std::vector<A*>
,或者如果您的元素是堆分配的,则最好使用某种智能指针的向量(C++11中的std::shared_ptr
或std::unique_ptr
,否则为boost::shared_ptr
或std::tr1::shared_ptr
)。
但是,即使您更改了以下内容,您的代码也无法正常工作:X
、Y
和Z
都按值取其参数,而向量中的所有元素都将具有类型A*
,因此取消引用它们将产生A
,因此它仍然会调用错误的方法。这可以通过将签名更改为始终采用A&
或A*
,并使用dynamic_cast
尝试将其转换为类型:来解决
class X
{
void foo(A*) { std:: cout << "A"; }
};
class Y : public X
{
void foo(A* p) {
if ( dynamic_cast<B*>(p) ) std::cout << "B"; // requires virtual methods in A
else X::foo(p);
}
};
class Z : public X
{
void foo(A*){
if ( dynamic_cast<C*>(p) ) std::cout << "C"; // requires virtual methods in A
else X::foo(p);
}
};
当然,dynamic_cast
的成本有点高,但如果这是一个问题,你可能需要重新考虑你的设计。此外,您需要确保A, B, C
包含一些virtual
方法(无论如何,virtual destructor
在这里是个好主意),因为否则dynamic_cast
将不起作用)
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将父类对象强制转换为子类的问题
- 调用具有未标识类型的类的方法
- 在运行时选择父类的实现
- C++ 中模板化类型的类层次结构
- 如何在C++子类中访问父类的私有变量
- 具有纯虚函数和指针数组对象类型的父类的指针数组
- 当函数返回类型为父类时,如何返回子类的对象?
- C 不能将带有父类指针作为类型的静态模板成员定义引用
- 比较从父类继承但存储在父类的向量中的类的对象类型
- 当父类共享指针为返回类型时返回新的基类
- 我能判断投射到父类中的对象类型最初是否是C++中的子类吗
- 在C++中将派生类类型的向量链接到父类类型的向量
- 在类中声明与父类具有相同类型的模板类
- c++中的多态性,父类的载体中的类型丢失
- 如何调用父类类型列表的子类的方法?C++
- 如何使用父类类型的智能指针调用子类的析构函数
- 将父类类型的成员驻留在另一个类中