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++ 强制转换自定义类的非指针实例的主要内容,如果未能解决你的问题,请参考以下文章

深入理解C++中五种强制类型转换的使用场景

深入理解C++中五种强制类型转换的使用场景

深入理解C++中五种强制类型转换的使用场景

C语言的多态是不是是类似于用结构指针的强制转换来实现的,具体实现方式类似于Linux万能链表???

虚拟多重继承和强制转换

尝试使用指向成员函数的指针时出现强制转换问题