Почему в реализации функции-члена тип результата не может быть описан с помощью определения в классе?
Реорганизовав некоторый код, я обнаружил, что если у меня есть определение функции-члена вне класса, его возвращаемый тип не может использовать имена, определенные с помощью "using" внутри этого класса.
#include <iostream>
class Foo {
public:
using Bar = int;
Bar f();
};
Bar Foo::f() {
return 42;
}
int main() {
std::cout << Foo().f();
return 0;
}
Этот код не будет компилироваться с ошибкой: "Bar" не называет тип. Я все еще могу использовать:
Foo::Bar Foo::f() {
return 42;
}
но с длинными именами это выглядит намного хуже.
Каковы причины этого? Почему я могу просто использовать Bar в качестве типа параметра, но должен добавить Foo::, чтобы использовать его в качестве возвращаемого типа?
2 ответа
Причина в том, где функция определена, что Bar
не входит в сферу. Это на самом деле Foo::Bar
и это не кандидат на совпадение с неквалифицированным именем Bar
вне определения класса.
Так что измените определение на
Foo::Bar Foo::f()
{
return 42;
}
Если вы хотите быть действительно ясными в пользу простых смертных, которые видят только заголовок, содержащий определение класса, также измените объявление функции (в определении класса) таким же образом.
Вы пытаетесь использовать использование Bar
в качестве возвращаемого типа, но этот тип не определен в вашей области видимости. Рассмотрите возможность использования typedef
лайк
#include <iostream>
typedef int Bar;
class Foo {
public:
Bar f();
};
Bar Foo::f() {
return 42;
}
int main() {
std::cout << Foo().f();
return 0;
}
РЕДАКТИРОВАТЬ: выяснить, почему ваш текущий код не работает без FOO::
(согласно предложению пользователя @swordfish) В вашем примере вы используете using
ключевое слово для объявления псевдонима типа внутри class Foo
, Эта функция была добавлена в C++ 11. Когда вы пытаетесь определить функцию класса вне класса, это using
внутри класса не видно, и поэтому вы должны предварять FOO::
чтобы это работало. это похоже на typedef
, но typedef
использование не будет идеальным, если вы хотите объявить класс Baz
в том же пространстве имен, которое выглядит так
class Baz {
public:
using Bar = double;
Bar f();
};
Baz::Bar Baz::f() {
return 42.1234;
}