You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ pImpl模式编译报错:对不完整类型应用sizeof无效

pImpl模式结合unique_ptr、propagate_const编译报错的解决方法

问题根源

你遇到的invalid application of 'sizeof' to an incomplete type错误,本质是编译器处理Main类头文件时,会自动尝试生成默认析构函数、移动构造函数和移动赋值运算符。这些操作需要std::unique_ptr<impl>访问impl的完整类型定义,但此时impl只是前向声明的不完整类型,导致sizeof操作失败。

具体修复步骤

1. 在头文件中声明Main的析构函数(仅声明不定义)

修改testclass.h的Main类,在public区域添加析构函数声明:

~Main();

这会阻止编译器在头文件中生成默认析构函数,将析构函数的定义推迟到cpp文件(此时impl已有完整定义)。

2. 在cpp文件中定义Main的析构函数

在testclass.cpp的Main构造函数定义后,添加析构函数的默认定义:

Main::~Main() = default;

无需手动编写析构逻辑,让编译器生成默认实现即可。

3. 修复代码小疏漏

  • Main::impl类定义末尾缺少分号,必须补上;
  • 使用cout需要包含<iostream>头文件,可添加using namespace std;或直接用std::cout;
  • 补充<memory>头文件,std::unique_ptr和std::make_unique依赖它。

修复后的完整代码

testclass.h

#include <experimental/propagate_const>
#include <memory>

class Main {
public:
    void main_f();
    Main();
    ~Main();
private:
    class impl;
    std::experimental::propagate_const<std::unique_ptr<impl>> pImpl;
};

testclass.cpp

#include "testclass.h"
#include <iostream>
#include <memory>

using namespace std;

class Main::impl {
private:
    int foo;
public:
    impl() = default;
    ~impl() {
        cout << "bye from impl";
    };
    impl(const impl&) = delete;
    impl& operator=(const impl& other) = delete;
    impl(impl&& source) noexcept = default;
    impl& operator=(impl&& other) noexcept = default;
};

Main::Main() : pImpl{std::make_unique<impl>()} {}

Main::~Main() = default;

main.cpp

#include "testclass.h"

int main() { 
    Main main;
    return 0;
}

额外说明

用std::unique_ptr实现pImpl时,务必确保所有需要操作impl完整类型的函数(如析构、移动构造/赋值),都在impl有完整定义的上下文(即cpp文件)中实现。通过显式声明析构函数并延迟定义,就能完美避开前向声明导致的不完整类型问题。

内容的提问来源于stack exchange,提问作者GaryO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:25:17