C++ 使用未定义类型
C++ Use Of Undefined Type
我有以下类:
class Logger {
public:
DEFAULT_CONSTRUCTOR(Logger);
DEFAULT_DESTRUCTOR(Logger);
NO_DEFAULT_COPY_AND_ASSIGN(Logger);
bool Init(std::wstring logFileLocation, std::wstring assemblyVersion);
void Shutdown();
void const LogMessage(std::wstring message);
private:
struct LoggerImpl;
std::unique_ptr<LoggerImpl> impl; // Error here
};
但是,在尝试编译时,我收到以下错误:
// Errors:
// Error 1 error C2027: use of undefined type 'ophRuntime::Logger::LoggerImpl'
// Error 2 error C2338: can't delete an incomplete type c:program files (x86)microsoft visual studio 12.0vcincludememory
// Warning 3 warning C4150: deletion of pointer to incomplete type 'ophRuntime::Logger::LoggerImpl'; no destructor called c:program files (x86)microsoft visual studio 12.0vcincludememory
Logger::LoggerImpl
在相应的.cpp文件中有一个定义:
struct LoggerStream::LoggerStreamImpl {
LoggerStreamImpl(std::wstring componentName) : componentName(componentName) { }
const std::wstring componentName;
NO_DEFAULT_COPY_AND_ASSIGN(LoggerStreamImpl);
};
最后,这些宏的定义:
#define NO_DEFAULT_COPY_AND_ASSIGN(TypeName)
TypeName(const TypeName&) = delete;
void operator=(const TypeName&) = delete;
TypeName(TypeName&&) = default;
#define DEFAULT_CONSTRUCTOR(TypeName) TypeName();
#define DEFAULT_DESTRUCTOR(TypeName) ~TypeName();
在标头中声明析构函数,并在源文件中定义它。
在 .h 中
class Logger {
public:
Logger(); // default constructor
~Logger(); // default destructor
private:
struct LoggerImpl; // impl forward declaration
std::unique_ptr<LoggerImpl> impl; // impl pointer
};
在.cpp
// Define the impl structure
struct Logger::LoggerImpl
{
};
// Define the default constructor
Logger::Logger() :impl(std::make_unique<LoggerImpl>())
{
}
// Define the default destructor
Logger::~Logger()
{
}
就是这样。
在你的情况下,你说LoggerImpl
是这样在.cpp中定义的,但我没有看到LoggerImpl
的定义,只是LoggerStreamImpl
的定义。
唯一指针的参数类型必须是实例化唯一指针的翻译单元中的完整类型:
struct Foo;
std::unique_ptr<Foo> p; // Error
当然,问题在于,如果没有完整的Foo
类型,就无法定义唯一指针的析构函数。如果您需要某种痘痘,您可以通过将析构函数延迟到单独的翻译单元来解决这个问题:
template <typename T> struct Impl
{
Impl();
~Impl();
std::unique_ptr<T> impl;
};
struct Foo
{
struct FooImpl;
Impl<FooImpl> impl;
};
int main()
{
Foo f;
}
此翻译单元进行编译,因为Foo::impl
的销毁留给析构函数Impl<FooImpl>::~Impl<FooImpl>
,该析构函数已声明(模板类Impl<FooImpl>
已完成),并且当前翻译单元中仅提供其定义。
再次强调这一切的重点:这里介绍的 pimpl 结构允许您将类Foo::FooImpl
的定义放入一个单独的私有翻译单元中,该类的使用者Foo
永远看不到。这种解耦的代价是额外的动态分配(在Impl<T>
的构造函数中)和额外的间接分配(在Foo
的成员函数的定义中,未显示),以及缺乏Impl<T>::impl
析构函数的内联。
有关更多详细信息,请参阅Herb Sutter的优秀GotW #101。
相关文章:
- 在UE4中使用未定义类型'UTextBlock'
- 删除[]具有不同类型的未定义行为?
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- 错误:未定义对"静脉类型信息::电池访问"的引用
- 在头文件中使用opencv类型来实现未定义的标识符
- 为什么这种类型的双关语不是未定义的行为?
- 在C++中,转换为simd类型是否有未定义的行为
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 交换未定义数据类型中的字节顺序
- 具有未声明/未定义类型的 typedef 结构
- 对静态常量积分类型的未定义引用
- 为什么 std::memcpy(作为类型双关语的替代方案)不会导致未定义的行为?
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- static_cast实际上不是对象类型的类型是未定义的行为吗?
- 共享库中非模板基的模板子类导致未定义的符号类型信息'class'链接错误
- icu::SimpleDate格式使用未定义类型的编译器错误
- 将不相关类型的对象reinterpret_cast空类是未定义的行为吗?
- 类型特征检查 CRTP 派生,在基类中,问题是未定义的类型
- std::is_arithmetic 为通用 lambda 中的 int 类型返回 false:未定义的行为?
- 使用 char16_t 类型作为 char[] 数组,并通过 reinterpret_cast<> 重新转换它。我的代码是否有未定义的行为?