Подтвердить что ты не робот

Предотвращение возврата частного внутреннего экземпляра класса

Я играл с внутренними классами в C++, и сейчас я немного запутался.

Мой код:

#include <iostream>

class outer{
private: 
    class inner{
    private:
        int something;
    public:
        void print(){
            std::cout<< "i am inner"<<std::endl;
        }   
    };
public:
    inner returnInner(){
        inner i;
        return i;
    }  
};

int main(){
    outer o;
    //outer::inner i = o.returnInner(); (1)
    //auto i = o.returnInner();         (2)
    //i.print();                  
    o.returnInner().print();          //(3)
    return 0;
}

Это скомпилировано в Linux с помощью clang++-3.5 и -std=c++14.

  • В (1) я получаю ошибку компилятора как ожидалось, потому что inner является частным внутренним классом outer.

  • Однако в (2), когда используется ключевое слово auto, компиляция выполнена успешно и программа запускается.

  • Все работает для (3).

Мой вопрос:

Почему это так? Могу ли я предотвратить возврат экземпляра частного внутреннего класса из внешних методов, сохраняя при этом возможность перемещать и/или копировать их во внешнем классе?

Не следует ли компилятору вызывать ошибку в (2) и (3), как в (1)?

4b9b3361

Ответ 1

почему это так Должна ли компилятор не возвращать ошибку в (2) и (3), как в (1)?

Это интересный вопрос.. и ответ на это еще интереснее.

В отправленном вами коде inner есть имя типа. Это имя, которое объявлено как private, а не сам тип 1 — доступность типа не имеет смысла в контексте С++; accessibilty относится только к имени — будь то имя типа, имя функции, имя данных. Поэтому, когда вы слышите что-то вроде "тип X является публичным классом", он почти всегда означает "имя X объявляется публичным, и оно относится к типу, а тип вездесущ, он существует повсюду".

Возвращаясь к тому, почему использование auto не дает ошибки, хорошо, потому что, когда вы используете auto, вы получаете доступ к типу без использования его имени, поэтому он не дает ошибки.

как я могу предотвратить возврат экземпляра частного внутреннего класса из внешних методов,

Нет способа.


1. struct { int data; } - это тип, без имени для ссылки, но обратите внимание, что это не является допустимым объявлением, потому что ему не хватает имени. Либо вы должны объявить объект неназванного типа, как в struct { int data; } obj; Или указать ему имя struct data_type { int data; };

Ответ 2

Я не уверен, что это то, что вы хотите, но вы можете удалить конструктор копирования следующим образом:

inner(inner const&) = delete;