C++嵌套在分离的头文件中

C++ nested class in separated header file

本文关键字:文件 分离 嵌套 C++      更新时间:2023-10-16

我想将嵌套类Inner从Outer.h移到一个分离的头文件中:

class Outer{
class Inner{
public:
Inner(Outer& o){}
};
public:
Outer():i(*this){}
~Outer(){}
Inner i;
};

对于"main.cpp">

#include "Outer.h"
int main(){
Outer o;
return 0;
}

但一旦我尝试将Inner类放在一个单独的头中,如下所示:

class Outer{
class Inner;
public:
Outer():i(*this){}
~Outer(){};
Inner i;
};

并将Inner类放置在'Inner.h'中,如下所示:

class Outer::Inner{
public:
Inner(Outer& o){}
};

并添加到主#include'Inner.h'中,如下所示:

#include "Outer.h"
#include "Inner.h"
int main(){
Outer o;
return 0;
}

我从编译器中得到以下错误:Outer.h:10:9:错误:字段"I"的类型不完整。

我或多或少地理解为什么,但我找不到一个问题来实现我想做的事情。

要创建Outer对象,类的内存布局必须是已知的,而在这种情况下,它不是(正是因为Inner的不完整性)。

这样做的方法是使用指针,然后正向声明将起作用(因为指针具有固定大小,然后Outer的内存布局将是已知的)。


我的意思是:

// header file
class Outer{
class Inner;
public:
Outer();
~Outer();
Inner* i;
};

然后,在类Outer的源文件中,定义

// include header file for Outer and Inner classes
// source file
Outer::Outer()
{
i = new Inner( *this );
};
Outer::~Outer()
{
delete i;
};

你需要在源文件中这样做,因为你需要includeInner的头文件(你不能直接在头文件中include它,因为你会遇到循环依赖(两个头文件将相互包括),因为Inner的头文件也需要Outer的头文件)。


这也被称为pImpl习语-"指向实现的指针",根据使用的编码约定,Inner通常被称为Impl和成员pImpl或类似的东西。这个想法是隐藏任何实现细节,比如私有/受保护的成员(函数、数据)。

如果不想将i成员变成指针,最好的选择是将Inner的定义移到Outer之外,并使用名称空间进行嵌套。

请注意,在这种情况下,您需要在Outer的定义之前包含Inner.h标头。