Тип параметра функции-члена является вложенным классом

#c #class

Вопрос:

 class Solution {
public:
    void func(test t)
    {

    }
    class test
    {

    };  
    
};
 

Компиляция этого приводит к ошибке

 error: unknown type name 'test'
    void func(test t)
 

Я добавил область в тест типа

 class Solution {
public:
    void func(Solution::test t)
    {

    }
    class test
    {

    };  
    
};
 

Но это дает

 test.cpp:47:25: error: no type named 'test' in 'Solution'
    void func(Solution::test t)
 

Я предполагаю, что это связано с тем, что функция test не знает о class test том, что она объявлена ниже. Поэтому я добавил объявление выше test

 class Solution {
public:
    class test;
    void func(Solution::test t)
    {

    }
    class test
    {

    };  
    
};
 

Теперь этот код компилируется (он также компилируется, если я удалю Solution:: область действия), но у меня есть 2 вопроса.

(1) Если func вызывается какая-либо другая функция-член, которая была определена ниже, она работает, но почему в этом случае она жалуется на незнание класса test ?

(2) Есть ли какой-либо смысл добавлять Solution:: в этой ситуации?

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

1. @RetiredNinja «Компиляторы читают сверху вниз» — но почему это не относится к ситуации, когда, например, func() вызывается другая функция, определенная ниже?

2. Объявления (включая прототипы определений функций в классе) обрабатываются сначала сверху вниз. Тела функций обрабатываются только после того, как известны объявления.

Ответ №1:

То, с чем вы здесь имеете дело, называется контекстом полного класса класса, который

Контекст полного класса класса (шаблона) является

  • тело функции ([dcl.fct.def.general]),
  • аргумент по умолчанию ([dcl.fct.по умолчанию]),
  • аргумент шаблона по умолчанию ([temp.param]),
  • описатель исключений ([кроме.spec]), или
  • инициализатор элемента по умолчанию

в пределах спецификации члена класса или шаблона класса.

Параметры функции-члена не являются частью этого, поэтому они должны быть типами, которые уже были определены, чего в данном случае нет. Это работает после class test; первого добавления, потому что теперь объявлен тип, и это все, что требуется для объявления функции.

Итак, решение состоит в том, чтобы test сначала определить или объявить его, как вы это делали в своем последнем примере.