C++ 强制转换自定义类的非指针实例
Posted
技术标签:
【中文标题】C++ 强制转换自定义类的非指针实例【英文标题】:C++ casting non-pointer instances of a custom class 【发布时间】:2014-04-06 02:59:32 【问题描述】:假设我有 A 类,它有一个子类 B。
class A
public:
A();
class B : public A
public:
B(int value) foo = value ;
int foo;
B 是具有 int foo 的 A 的子类。
好的,现在假设我执行以下操作:
std::vector<A> mylist;
B myB(5); //Create a new instance of class B
mylist.push_back(myB); //Add b to my vector of A.
现在我想访问 mylist 的一个元素并将其类型转换为类型 B 并检索“foo”。以下是否合法?
B *instance = (B *)&mylist[0];
我已经在我的项目中尝试过这样做,但是如果我要打印出 foo 的值,那将是不正确的:
std::cout<<instance->foo<<std::endl; // This does not give me 5. It gives me a garbage number.
问题源于我不知道在 C++ 中转换非指针的正确方法。
【问题讨论】:
Okay now lets say I do the following:
不要。既然你不应该这样做,那么你剩下的问题就变成了一个有争议的问题。
^那么我正在尝试找出正确的方法来投射非指针......
What is the slicing problem in C++?的可能重复
如果你的向量包含 A 对象,那么它应该只知道 A 对象。假设您现在更改向量以保存指向 A 对象的指针。尽管如此,向量应该只知道 A 指针,并且您应该只使用 A 接口。所以我要说的是你应该重新考虑你的设计。也许引入虚函数。
没有正确的方法。
【参考方案1】:
当您编写mylist.push_back(myB)
时,会出现一个切片。 mylist
存储 A
对象。因此,您的B
被转换为A
,丢失了B
而不是A
中的所有内容。仅存储A
。您无法找回丢失的碎片。
和做的一样:
B myB(5);
A a(myB);
为了具有多态行为,您需要使 A
成为多态类,并通过指针引用对象,即 A *
。
所以你需要向A
添加至少一个虚函数(虚析构函数是个好主意),并让你的向量存储指针。例如:
std::vector< A* > mylist;
mylist.push_back( new myB(5) );
B *instance = dynamic_cast<B *>(mylist[0]);
现在,这段代码没问题,但您必须非常小心地删除新创建的内存。为了解决这个问题,shared_ptr
是一个引用计数的指针。我做了以下似乎有效的测试用例(免责声明 - 我不是智能指针多态性方面的专家,所以我希望这里没有隐秘错误)
#include <iostream>
#include <memory>
#include <vector>
class A
public:
A();
virtual ~A()
;
class B : public A
public:
B(int value): foo(value)
int foo;
~B() std::cout << "Destructor B(" << foo << ")" << std::endl;
;
int main()
std::vector< std::shared_ptr<A> > mylist;
// Test the polymorphic behaviour
// mylist.push_back( std::make_shared<A>() );
// create directly into container
mylist.push_back( std::make_shared<B>(5) );
// via pointer
B *temp_b = new B(6);
mylist.push_back( std::shared_ptr<B>(temp_b) );
std::shared_ptr<B> instance = std::dynamic_pointer_cast<B>( mylist[0] );
if ( !instance )
std::cout << "Item was not a B" << std::endl;
else
std::cout << instance->foo << std::endl;
【讨论】:
【参考方案2】:这是一个典型的 C++ 切片问题示例。
您应该将指针存储在向量中以轻松避免它们。如果您不想处理原始指针,请使用智能指针。
【讨论】:
什么是切片?有没有办法让我在没有指针的情况下这样做? @lizusek:类型字段有什么帮助?推送时仍然会发生切片。以上是关于C++ 强制转换自定义类的非指针实例的主要内容,如果未能解决你的问题,请参考以下文章