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
相关产品推荐
相关产品推荐

