Используйте директиву using для закрытого вложенного класса

Некоторое время я разрабатывал библиотеку, и теперь, когда я думаю, что она готова, я пытаюсь следовать принцип прыщ чтобы скрыть детали реализации.

// 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 ?

0

Решение

Есть ли способ использовать с помощью частного вложенного класса ClassImpl?

Да. декларировать ClassImpl с публичной видимостью в Class:

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

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

// ...

using C = Class::ClassImpl;

Живая демо

Вы также можете сделать ClassImpl не вложенный класс.

Примечание: вы можете предпочесть Class::rep быть ссылкой, а не (голым) указателем. Там нет никаких оснований для действительного Class экземпляр не должен иметь объект реализации (нулевой указатель).

0

Другие решения

Есть ли способ использовать 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 имя (вложенного класса) Class, private а также protected Имена классов не могут быть доступны в области видимости файла.

0