【问题标题】:partial forward declaration in c++C ++中的部分前向声明
【发布时间】:2019-12-10 20:35:07
【问题描述】:

我有一个项目 (A) 使用另一个 (B) 的类,但是包含 B 的标头会使 A 的编译非常混乱,而单独的编译工作正常(但在这种情况下我不能使用 B 的类A)。

B用VS2019的编译器v142编译,A用cuda 10的nvcc编译。

如何只转发声明少数成员,例如构造函数、属性和方法?

在 A 中,我想使用没有 B 标题的代码:

DX12Cuda = new DX12CudaInterop(ImUtil.ImFeatures.Width, ImUtil.ImFeatures.Height, L"DX12Cuda", funcMessage);
DX12Cuda->CuSurfaceUpdater = [&](cudaSurfaceObject_t o) {UpdateCuSurface(o); };
OnRenderDX12 = [&]() {DX12Cuda->OnRender(); };
DX12Cuda->OnInit(hwnd);

在 B 中:

class DX12CudaInterop
{
public:
    DX12CudaInterop(UINT width, UINT height, wstring name, MessageChangedCallback managedDelegate);
    function<void(cudaSurfaceObject_t)> CuSurfaceUpdater;
    OnInit(HWND hwnd);
    OnRender();
}

void DX12CudaInterop::OnInit(HWND hwnd) {/*...*/}
void DX12CudaInterop::OnRender() {/*...*/}

错误示例:

严重性代码描述项目文件行抑制状态 错误标识符“NPP_MIRROR_FLIP_ERR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 412 错误名称后跟“::”必须是类或命名空间 名称 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 3
错误标识符“字节”是 未定义 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 29
错误名称后跟“::”必须是类或命名空间 名称 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 31
错误名称后跟“::”必须是类或命名空间 名称 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 41
错误预期 “;” ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 41
错误标识符“文件”是 未定义 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 42
错误标识符“字节”是 未定义 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 52
函数声明中允许的错误内联说明符 只有 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 63
错误不完整类型不是 允许 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 63
错误标识符“ID3D12Object”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 63
错误标识符“pObject”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 63
错误预期 ")" ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 63
错误预期 “;” ShCuSum path_to_solution\D3D12CudaUpdateFull\DXSampleHelper.h 64
错误标识符“IDXGIFactory2”是 未定义 ShCuSum path_to_solution\D3D12CudaUpdateFull\DX12CudaSample.h 30
错误标识符“IDXGIAdapter1”是 未定义 ShCuSum path_to_solution\D3D12CudaUpdateFull\DX12CudaSample.h 30
错误标识符“NPP_BAD_ARG_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 323 错误标识符“NPP_COEFF_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 326 错误标识符“NPP_RECT_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 329 错误标识符“NPP_QUAD_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 332 错误标识符“NPP_MEM_ALLOC_ERR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 335 错误标识符“NPP_HISTO_NUMBER_OF_LEVELS_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 338 错误标识符“NPP_INVALID_INPUT”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 341 错误标识符“NPP_POINTER_ERROR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 344 错误标识符“NPP_WARNING”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 347 错误标识符“NPP_ODD_ROI_WARNING”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 350 错误标识符“NPP_MEMFREE_ERR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 403 错误标识符“NPP_MEMSET_ERR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 406 错误标识符“NPP_MEMCPY_ERR”是 未定义的 ShCuSum path_to_solution\D3D12CudaUpdateFull\helper_cuda.h 409 错误(活动)E0135 类“Microsoft::WRL::Details::EnableIf”没有成员“类型”D3D12CudaUpdate C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt\wrl\client.h 379

【问题讨论】:

  • 你不能。如果您解释其背后的问题,也许我们可以提供帮助。 IE。 A 的定义(不是声明!)可以进入 cpp 文件吗?
  • 我认为您必须创建一个最小的示例。并且也许提及您正在使用的编译器。
  • 你基本上不能。标准做法是在需要它的类的头文件中前向声明该类,然后在需要它的类的 CPP 文件中包含相关的头文件。基本上你需要this
  • “使编译...非常混乱”是什么意思?您能否详细说明您要解决的问题?显示一些代码可能会有所帮助。

标签: c++ winapi


【解决方案1】:

你不能。您可以这样做:

// interop.h, shared across the project
class iCudaInterop
{
public:
    virtual ~iCudaInterop() { }
    virtual void OnInit( HWND hwnd ) = 0;
    virtual void OnRender() = 0;
};
extern std::unique_ptr<iCudaInterop> createInterop( UINT width, UINT height, const std::wstring& name, MessageChangedCallback del );

// interop.cpp, only in project B
#include "interop.h"

class CudaInterop : public iCudaInterop
{
    DX12CudaInterop m_impl;

public:
    CudaInterop( UINT width, UINT height, const std::wstring& name, MessageChangedCallback del ) :
        m_impl( width, height, name, del ) { }
    ~CudaInterop() = default;

    void OnInit( HWND hwnd ) override { m_impl.OnInit( hwnd ); }
    void OnRender() override { m_impl.OnRender(); }
};

std::unique_ptr<iCudaInterop> createInterop( UINT width, UINT height, const std::wstring& name, MessageChangedCallback del )
{
    return std::make_unique<CudaInterop>( width, height, name, del );
}

对于该属性,简单的方法是在实现 get/set 的 m_impl 字段时将 iCudaInterop 接口的另外 2 个抽象方法 getter 和 setter 包装起来。

【讨论】:

  • 是否可以将智能指针分配给字段?当字段的类也将被删除时,它的“超出范围”是否会被调用?
  • @Soleil 通常是的,但您需要牢记生命周期。 std::unique_ptr 是类实例的单一所有者。当智能指针被销毁时(如果它是局部变量或类字段的析构函数超出范围),引用的对象也将被销毁。您可以使用std::moveunique_ptr::swap 将所有权转移给另一个智能指针。
猜你喜欢
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 2021-12-25
相关资源
最近更新 更多