Прямой базовый класс частного наследования не позволяет производному классу определять объект косвенного базового класса

#c #private-inheritance

#c #private-наследование

Вопрос:

например, этот код

 class Try
{
public:
    Try() = default;
    int i = 0;
};

class B1 : private Try
{
public:
    B1() = default;
    using Try::Try();
    using Try::i;
};

class C1 : public B1
{
public:
    Try a; //tell me:'Try' is a private member of 'Try'
    
    void print()
    {std::cout << i << std::endl;}
    //Access to this I is allowed;
};
 

Попытка a является локальным объектом, а не частью C1, почему ошибка?

Если это прямой базовый класс частного наследования, разве невозможно определить объект косвенного базового класса в его производном классе? Это потому, что конструктор нельзя использовать или по другим причинам?

Комментарии:

1. Не могли бы вы опубликовать полное сообщение об ошибке дословно на свой вопрос?

Ответ №1:

Попытка a является локальным объектом, а не частью C1, почему ошибка?

При записи Try a; в контексте class C1 поиск имени обычно всегда будет сканироваться из локальной области в глобальную. Таким образом, первое совпадение будет B1::Try , которое из-за частного наследования недоступно для C1 .

Исправить это легко, просто намекните компилятору имя, которое вы «действительно» имеете в виду, т. Е. написав, например ::Try a; .

Комментарии:

1. Я понимаю, что класс c1 принадлежит локальной области видимости. Я все еще не понимаю, почему локальное действие не может определить объект? Это из-за частного наследования?

2. @Nater Да, вы получаете доступ Try «через призму» B1 , поскольку B1 следующий контекст для компилятора для поиска имени Try , который недоступен C1 . Тем не менее, B1::Try действительно существует (из-за наследования), но он недоступен для C1 (поскольку наследование является частным), поэтому извне B1 недопустимо утверждать, что B1 это производное от Try . Компилятору все равно, B1::Try доступен он или нет, он нашел имя, которое работает, и останавливает поиск другого Try . Вот почему вы должны получить доступ Try на глобальном уровне, ::Try чтобы дать подсказку.

3. У меня есть некоторое понимание, но у меня все еще есть вопрос: пока это частное наследование, невозможно ли определить объект косвенного базового класса в его производном классе? Хотя конструктор прямого базового класса объявлен как общедоступный, я внес некоторые изменения в код

4. @Nater Нет, это не невозможно. Как я уже писал, если вы обращаетесь к нему с помощью ::Try a; , вы можете определить объект косвенного типа базового класса, когда действует частное наследование. Сделав конструктор доступным, вы все равно не сможете его использовать B1::Try , поскольку с точки зрения контроля доступа любое предположение о наследовании запрещено (из-за конфиденциальности).

5. @Nater — Нет — как говорится в этом ответе — частное наследование не препятствует использованию экземпляра базового класса в качестве члена производного класса. Необходимо убедиться, в контексте C1 , что тип члена назван правильно (т. Е. Что член указан как ::Try a , а не Try a как ). ::Try является полным именем Try , в вашем примере.