【问题标题】:Hiding pointer member implementation from header file从头文件中隐藏指针成员实现
【发布时间】:2020-04-23 02:26:17
【问题描述】:

我正在使用 library - nlohmann/json 并希望有一个指向 json 的成员供内部使用。

我想避免将整个库作为编译时依赖项,所以我考虑使用指向前向声明结构的指针

在标题中

struct my_json; // forward declare 

std::unique_ptr<my_json> memberJson;

在 cpp 中:

struct my_json : public nlohmann::json {};

但问题是当我尝试在课堂中使用它时,我得到了任何一个

error C2440: '=': cannot convert from 'nlohmann::json *' to 'my_json *'

当尝试将reference operator[](const typename object_t::key_type&amp; key) 的结果地址分配回my_json *

error C2440: 'initializing': cannot convert from 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>' to 'my_json  &'

当尝试将reference operator[](const typename object_t::key_type&amp; key) 的结果直接分配给my_json &amp;

有没有一个优雅的解决方案? (如果我想避免reinterpret_casting 指针)在这种情况下static_casting 安全吗?

【问题讨论】:

  • 我想class my_jsonstruct my_json 是错字?
  • 通过struct my_json : public nlohmann::json {}; 形式的继承,my_json * 可以隐式转换为nlohmann::json *(即从派生到基)。反向(从基础到派生的转换)无效。在不知道为什么要尝试以错误的方向进行转换的情况下,实际上不可能就解决方案提出建议。
  • @ThomasCaissard - 在这种情况下,两者之间没有真正的区别。 classstruct 是相同的,除了 struct 的默认访问和默认继承是 publicclassprivate
  • @Peter 我有一个成员集合,它也存储指向my_json * 的指针,还有一些内部函数希望在它们之间与my_json * 进行通信(例如返回值或参数)。声明必须在标题中,所以我“卡住”了将其定义为 my_json * 而不是真正的类型。如果我 static_cast&lt;my_json*&gt; 编译它,那么它定义得很好(假设继承就是这样并且没有引入任何东西)
  • static_cast 将起作用,甚至在需要时调整指针(例如,用于多重继承)。但是,如果您的指针不指向动态类型 my_json 的对象(或从它派生的类型),您将获得未定义的行为。

标签: c++ templates c++14


【解决方案1】:

为什么不转发声明nlohmann::json

namespace nlohmann { class json; }

编辑:我用过json_fwd.hpp.(https://github.com/nlohmann/json/blob/master/include/nlohmann/json_fwd.hpp)

标题:

#pragma once
#include "json_fwd.hpp"
#include <memory>

class A {
    std::unique_ptr<nlohmann::json> ptr;

    public:
        A();
        ~A();
};

实施:

#include "Header.h"
#include "json.hpp"

A::A() :
    ptr(std::make_unique<nlohmann::json>()) {

    (*ptr)["Hallo"] = 2;
}

A::~A() = default;

【讨论】:

  • IIRC nlohmann::json 实际上是一个模板实例的 typedef,它有一堆策略作为参数,所以这是行不通的。这让我非常痛苦。
  • @Quentin 这是否意味着您不能以这种方式转发声明?
  • @Quentin 是对的,当 nlohmann::json 被前向声明时它不会编译(参见github.com/nlohmann/json/issues/314)。我的错,我之前没试过。
  • 自定义删除器是多余的:只需在标头中声明~A(); 并在.cpp 文件中定义A::~A() = default;,默认删除器将起作用:) -- 无论如何,json_fwd.h 是绝对是为此目的而制作的(因此有_fwd 后缀),非常好。
  • 感谢您的改进,我已经修改了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 2021-12-22
相关资源
最近更新 更多