1

我一直在开发一个库,现在我认为它已经准备好了,我正在尝试遵循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;
}

这样做,编译器error: 'class Class::ClassImpl' is private会在ClassImpl.cpp. 如果我将其删除并Class::ClassImpl改用,一切正常。

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

4

2 回答 2

1

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

最简洁的答案是不”。

更长的答案如下。

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

您的使用声明

using C = Class::ClassImpl;

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

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

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

如果您想using根据您的示例在文件范围内声明;

using C = Class::ClassImpl;

然后ClassImpl需要是 . 的public(嵌套类的)名称Classprivate并且protected不能在文件范围内访问类的名称。

于 2019-01-02T12:36:07.497 回答
1

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

是的。在以下位置声明ClassImpl具有公共访问权限Class

class Class {
public:
    Class();
    class ClassImpl;

private:
    ClassImpl* rep; // should be reference, see note.
};

// ...

using C = Class::ClassImpl;

现场演示

您也可以ClassImpl不创建嵌套类。

注意:您可能更喜欢Class::rep成为引用而不是(裸)指针。有效实例没有理由Class没有实现对象(空指针)。

于 2019-01-02T11:50:24.230 回答