【问题标题】:Use the using directive on a private nested class在私有嵌套类上使用 using 指令
【发布时间】:2019-05-29 01:14:33
【问题描述】:

我一直在开发一个库,现在我认为它已经准备好了,我正在尝试关注 pimpl principle 以隐藏实现细节。

// 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 的 using 行上显示 error: 'class Class::ClassImpl' is private。如果我删除它并改用Class::ClassImpl,一切正常。

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

【问题讨论】:

  • 您引用的页面末尾的示例是否与您做同样的事情?他们是否也尝试在main() 函数中使用usingwidget 类的impl?没有。
  • @JoeyMallone 否,因为它们在类声明中定义了函数。在示例页面中这似乎是一个好主意,但因为我的实现是一百行长,所以它对我来说还不够
  • 试试这个ClassImpl::ClassImpl() {作为构造函数,留下using
  • 我没有什么可以支持这一说法(因此仅作为评论),但不,这是不可能的。您正在尝试创建一个alias。想象一下,如果您可以为任何私有符号创建别名。那会破坏访问修饰符的全部目的,不是吗?无论如何,虽然我讨厌预编译器,但您可以通过简单地定义一个常量来实现相同的代码缩减:#define C Class::ClassImpl

标签: c++ class-visibility


【解决方案1】:

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

是的。声明 ClassImpl 并在 Class 中公开访问:

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

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

// ...

using C = Class::ClassImpl;

Live demo

您也可以使ClassImpl 不是嵌套类。

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

【讨论】:

  • 裸指针只是示例,我实际使用智能指针
【解决方案2】:

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

简短的回答是“不”。

下面是更长的答案。

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

你的使用声明

using C = Class::ClassImpl;

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

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

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

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

using C = Class::ClassImpl;

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

【讨论】:

    猜你喜欢
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多