Используйте директиву using для закрытого вложенного класса - PullRequest
0 голосов
/ 02 января 2019

Я некоторое время разрабатывал библиотеку, и теперь, когда я думаю, что она готова, я пытаюсь следовать принципу 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?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Есть ли способ использовать using для частного вложенного класса ClassImpl?

Краткий ответ - "нет".

Более длинный ответ следует.

То, что вы пытаетесь сделать, - это объявление using, а не директива using.

Ваше объявление об использовании

using C = Class::ClassImpl;

находится в области видимости файла, поэтому имя Class::ClassImpl нельзя использовать непосредственно в качестве имени в этой области.

Первым соответствующим разделом стандарта (C ++ 17) является Раздел 10.3.3 «Объявление using», в котором пункт 19 гласит «Синоним, созданный using-декларацией , имеет обычная доступность для декларации члена".

Чтобы узнать, что подразумевается под «обычной доступностью», обратитесь к Разделу 14 «Контроль доступа членов», в котором говорится, что «private имена могут использоваться только членами и друзьями класса, в котором оно объявлено». Использование «имён» здесь довольно специфично - все с именем, равным private для класса (объявления членов, объявления типов и т. Д.), Обрабатывается одинаково.

Если вы хотите иметь using объявление в области видимости файла, как в вашем примере;

using C = Class::ClassImpl;

тогда ClassImpl должно быть public именем (вложенного класса) Class. private и protected имена классов недоступны в области видимости файла.

0 голосов
/ 02 января 2019

Можно ли использовать закрытый вложенный класс 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 нет причины не иметь объект реализации (нулевой указатель).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...