在私有嵌套类上使用 using 指令

Use the using directive on a private nested class

本文关键字:using 指令 嵌套      更新时间:2023-10-16

我已经开发了一个库一段时间了,现在我认为它已经准备好了,我正在尝试遵循 pimpl 原则以隐藏实现细节。

// File Class.h
class Class {
public:
Class();
private:
class ClassImpl;
ClassImpl* rep;
};
// File Class.cpp
#include "Class.h"
#include "ClassImpl.h"
Class::Class() {
rep = new ClassImpl();
}

实现类在另一个文件中定义如下

// File ClassImpl.h
#include "Class.h"
class Class::ClassImpl {
public:
ClassImpl();
};

及其实现:

// File ClassImpl.cpp
#include "ClassImpl.h"
#include <iostream>
using C = Class::ClassImpl; // error: 'class Class::ClassImpl' is private
C::ClassImpl() {
std::cout << "Implementation constructor";
}

主要功能:

// File main.cpp
#include "Class.h"
int main() {
Class c;
return 0;
}

这样做,编译器在ClassImpl.cpp中的使用行上说error: 'class Class::ClassImpl' is private。如果我删除它并改用Class::ClassImpl,一切正常。

有没有办法在私有嵌套类ClassImpl上使用using

有没有办法在私有嵌套类ClassImpl上使用using

简短的回答是"不"。

接下来是更长的答案。

您要做的是一个using声明,而不是一个using指令。

您的使用声明

using C = Class::ClassImpl;

位于文件范围内,因此名称Class::ClassImpl不能直接用作该范围内的名称。

标准的第一个相关部分(C++17)是第10.3.3节"using声明",其中第19段指出">由使用声明创建的同义词具有成员声明通常的可访问性"。

要了解"通常可访问性"的含义,请参阅第 14 节"成员访问控制",其中指出"private名称只能由声明它的班级的成员和朋友使用"。 这里"名称"的用法非常具体 - 任何具有与类private的名称(成员声明、类型声明等)都以相同的方式处理。

如果您想在文件范围内有一个using声明,如您的示例所示;

using C = Class::ClassImpl;

那么ClassImpl需要是Classpublic名称(嵌套类的)。 无法在文件范围内访问类的privateprotected名称。

没有办法在私有嵌套类 ClassImpl 上使用?

是的。在Class中声明具有公共访问权限的ClassImpl

class Class {
public:
Class();
class ClassImpl;
private:
ClassImpl* rep; // should be reference, see note.
};
// ...
using C = Class::ClassImpl;

现场演示

您还可以ClassImpl不是嵌套类。

注意:您可能希望Class::rep作为引用而不是(裸)指针。有效的Class实例没有理由没有实现对象(空指针)。