【问题标题】:Static casting to unique_ptr静态转换为 unique_ptr
【发布时间】:2019-06-13 01:06:15
【问题描述】:

我有一个头文件,出于复杂性和“保密”的原因,它需要隐藏一些内部结构。因此,我在 oublic 标头中声明了一个原始 void 指针,在代码内部有静态转换将原始指针转换为它的实际类型。

现在由于一般内存管理更改,我需要在内部将类型更改为 unique_ptr(它现在作为 unique_ptr 来自对象工厂,以前是原始指针)。

所以在我的标题中我有这个:

class SomeClass {
    private:
    void *_hiddenTypeInstance;
}

是否可以将此 _hiddenTypeInstance 静态转换为内部已知的 unique_ptr 类型?

【问题讨论】:

  • 它本身是unique_ptr 吗?还是它指向unique_ptr
  • 可以将 unique_ptr<Foo *> 转换为 void * 并再次返回,如果这就是您的要求
  • 也许看看“pimpl idiom”
  • 一般来说,如果你可以声明一个空的基类并使用指向它的指针作为你的“秘密”而不是空指针会更好。您还可以声明类型的名称而不定义其内容。这两者都确保数据的内容保持合理的机密性,但允许调用者编写比使用 void* 更不容易出错的代码。如果他们有多个 void* 对象,您如何确定他们已将您的对象还给您?

标签: c++11 c++14


【解决方案1】:

这不是您想要的直接答案,而是如何将事情做得更好的建议:) 实际上,您仍然可以使用 std::unique_ptr 的内存语义,隐藏内部而不使用丑陋的 void*。正如其他人所提到的,您应该研究 PIMPL,但总结一下:

  1. 在公共标头中转发声明内部类型
  2. std::unique_ptr 与该类型一起使用并为包含该成员的类提供一个dtor(否则您将收到编译错误,因为将生成一个默认dtor,它将尝试删除前向声明的类并且将无法执行所以)。

这看起来像这样:

#include <memory>

class CPrivate; // Forward declare the internal class

class CPublic
{
public:
    // You need the dtor here, since when you implement it in the .cpp of your library,
    // where the definition of CPrivate is known, the dtor of std::unique_ptr will know how to delete it.
    // If you do not put the dtor here, a default one will be generated here which invokes the dtor of std::unique_ptr, and here
    // since CPrivate is forward declared the dtor of std::unique_ptr will not know how to delete it and you will get an error
    ~CPublic();


private:
    std::unique_ptr<CPrivate> m_pPrivate;
}

通过使用它,您可以将实现内部的转换从void* 转义为实际类型。

至于原始问题 - 您始终可以将 void* 转换为 std::unique_ptr&lt;T&gt;*(指向 unique_ptr 的指针)。但我建议评估上述解决方案。因为 void* 的东西消除了所有类型的严格性 - 例如,如果有人更改 T 会发生什么?

【讨论】:

  • 谢谢,我想我将不得不接受静态演员表,即使它提到了缺点。我的问题是我无法在公共标头中公开类的名称。
  • @benjist 即使它是前向声明的?在你的情况下有什么缺点?例如。 Qt 做到了——他们在所有公共头文件中转发定义 QXXXPrivate。
【解决方案2】:

如果我以正确的方式理解您的问题:您可以这样做。这个例子只是为了理解一个概念。您可以在自己的代码中使用它。由于我没有完整的代码,我无法编写确切的解决方案。

class SomeClass {
private:
    void *_hiddenTypeInstance;
public:
    std::unique_ptr<int> foo() {
        int a;
        a = 2;
        return std::unique_ptr<int>(&a);
    }
    void bar() {
        std::unique_ptr<int> temp_hidden_type_instance;
        temp_hidden_type_instance = std::unique_ptr<int>(static_cast<int*>(_hiddenTypeInstance));
        temp_hidden_type_instance = foo();
    }
};

【讨论】:

  • 我不知道你想做什么,但它肯定不会起作用,因为它会尝试删除一个甚至不再存在的局部变量。
  • 这样做是你从这个类之外的任何方法中获得一个 unique_ptr。您可以将 hiddenType 转换为该 unique_ptr 并使用它,它将自动被删除。如果要存储它,则需要将另一个成员变量声明为 unique_ptr m_hiddenTypeInstance 作为私有成员变量。我以为你只是想转换它并使用它。
猜你喜欢
  • 2012-06-15
  • 2018-12-15
  • 2014-03-27
  • 2020-01-30
  • 2021-02-18
  • 2017-02-15
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多