Некоторое время я разрабатывал библиотеку, и теперь, когда я думаю, что она готова, я пытаюсь следовать принцип прыщ чтобы скрыть детали реализации.
// 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
?
Есть ли способ использовать с помощью частного вложенного класса 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
экземпляр не должен иметь объект реализации (нулевой указатель).
Есть ли способ использовать
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
Имена классов не могут быть доступны в области видимости файла.