Здравствуйте, johny5, Вы писали:
J>Встретил в коде обескураживающее место.
Ну так почитай наконец-то какую-нибудь книжку по с++ и такие места не будут обескураживать
J>Однако увидел пример такого: J>
J>// header такой же
J>//cpp file
J>using namespace N;
J>void C::func()
J>{
J> ..
J>}
J>
Ты не поверишь, но ещё можно и так:
//cpp filevoid N::C::func()
{
..
}
J>Попинайте, разве как во втором случае — предпочтительнее писать?
Как тебе в данный момент удобно, так и предпочтительнее
Здравствуйте, johny5, Вы писали:
J>Всем привет.
... J>Попинайте, разве как во втором случае — предпочтительнее писать? Есть ли какая разница между двумя конструкциями.
Если в глобальном пространстве имен появится еще один класс С, то вариант "namespace N {" сразу станет более удобным.
Одноименные классы могут сыскаться и в std::, и в boost:: ... , а "using namespace std" почти общеупотребительная практика для .cpp .
Более того, одноименные классы могут внезапно появиться, с обновлением boost, или компилятора...
Здравствуйте, Chorkov, Вы писали:
C>Здравствуйте, johny5, Вы писали:
J>>Всем привет. C>... J>>Попинайте, разве как во втором случае — предпочтительнее писать? Есть ли какая разница между двумя конструкциями.
C>Если в глобальном пространстве имен появится еще один класс С, то вариант "namespace N {" сразу станет более удобным. C>Одноименные классы могут сыскаться и в std::, и в boost:: ... , а "using namespace std" почти общеупотребительная практика для .cpp . C>Более того, одноименные классы могут внезапно появиться, с обновлением boost, или компилятора...
Понятно.
Не знал что при definition-е функции компилятор также занимается поиском в пространствах имён к какому именно это определение относится. Что компилер ищет про неймспейсам при использовании чего то (класса, функции) — это общеизвестно, но вот этот случай я вижу вообще впервые. Имхо это ненужная диковинка для гиков
Здравствуйте, johny5, Вы писали: J>Здравствуйте, Chorkov, Вы писали:
J>Понятно. J>Не знал что при definition-е функции компилятор также занимается поиском в пространствах имён к какому именно это определение относится. Что компилер ищет про неймспейсам при использовании чего то (класса, функции) — это общеизвестно, но вот этот случай я вижу вообще впервые. Имхо это ненужная диковинка для гиков
Кстате, не заработало для перегрузки operator++ для enum:
namespace N
{
enum Blabla
{
};
// prefix (++my_member)
Blabla& operator++(Blabla& orig);
// postfix (my_member++)
Blabla operator++(Blabla& orig, int);
}
using namespace N;
// prefix (++my_member)
Blabla& operator++(Blabla& orig)
{
return orig;
}
// postfix (my_member++)
Blabla operator++(Blabla& orig, int)
{
return ++orig;// error C2593: 'operator ++' is ambiguous
// could be 'N::Blabla &operator ++(N::Blabla &)'
// or 'N::Blabla &N::operator ++(N::Blabla &)'
// while trying to match the argument list '(N::Blabla)'
}
Если поместить операторы в namespace N — работает.
Возможно баг компайлера, VS2010.
Здравствуйте, ArtDenis, Вы писали:
AD>Как тебе в данный момент удобно, так и предпочтительнее
Предпочтительнее не использовать using в подобных контекстах (в заголовочном файле), поскольку ваш заголовочный файл может включаться в другой заголовочный файл, где такой using будет нежелательным.
Здравствуйте, johny5, Вы писали:
J>Кстате, не заработало для перегрузки operator++ для enum:
Потому что уточнение контекста для определений функций — это забавная штука.
namespace N {
class C {
typedef int D;
D member(D x);
};
}
N::C::D // здесь контекст ещё самый верхний, namespace :: - поэтому нужно тип квалифицировать полностью
N::C::member // по этой же причине полностью квалифицируем имя члена
( // а вот с этого места контекст - N::C::
D x
)
{ ... }
// вышли из определения - вернулись к исходному ::
///////////////auto// чёрт его знает, какой тип
N::C::member
(D x) -> D // в этой строке уже известно про N::C
{ ... }
Опять же,
namespace N
{
class T {};
void foo(T); // объявили N::foo(N::T)
}
using namespace N;
void foo(T); // объявили ::foo(N::T)void foo(T) {...} // определили ::foo(N::T)int main()
{
// в поле зрения есть и ::N::foo, и ::foo
foo(T());
}
К>namespace N
К>{
К> class T {};
К> void foo(T); // объявили N::foo(N::T)
К>}
К>using namespace N;
К>void foo(T); // объявили ::foo(N::T)
К>void foo(T) {...} // определили ::foo(N::T)
К>int main()
К>{
К> // в поле зрения есть и ::N::foo, и ::foo
К> foo(T());
К>}
К>
Хорошо, это всё так, для функций. А почему (возвращаясь к изначальному вопросу) не так для методов?
Вот к примеру в коде:
// common_header.hnamespace N
{
struct T
{
static void static_method();
void method();
};
void func();
}
// file1.cpp#include"common_header.h"using namespace N;
void T::static_method() {}
void T::method() {}
void func() {}
// file2.cpp#include"common_header.h"void test()
{
T t;
t.method(); // линкуется успешно
T::static_method(); // линкуется успешно
func(); // не линкуется
}
Я конечно догадываюсь почему, но хочется увидеть точный, обстоятельный ответ от знающего человека. Я вижу что разница в определении метода в том, что я в любом случае указываю тип класса, а (я догадываюсь что) типы, даже в определении метода, всегда ищутся во всех видимых неймспейсах.
PS: Я таки нашёл главную разницу, свободные функции, объявлённые в namespace, не связываются при их определении без явного указания их неймспейса, а методы связываются. Теперь можно бегать и тыкать носом народ
Здравствуйте, johny5, Вы писали:
J>Хорошо, это всё так, для функций. А почему (возвращаясь к изначальному вопросу) не так для методов? J>Я конечно догадываюсь почему, но хочется увидеть точный, обстоятельный ответ от знающего человека. Я вижу что разница в определении метода в том, что я в любом случае указываю тип класса, а (я догадываюсь что) типы, даже в определении метода, всегда ищутся во всех видимых неймспейсах.
Именно: когда встречается квалифицированное имя, T::method, — ищется его объявление. Для чего требуется сперва найти, что такое T и где оно объявлено
А определение функции с неквалифицированным именем — это, одновременно, её объявление в текущем неймспейсе.
Поэтому и получается, что одна функция объявлена в неймспейсе N и не определена, а вторая определена в неймспейсе ::, но не объявлена в file2.cpp, поэтому компилятор её и не искал.
J>PS: Я таки нашёл главную разницу, свободные функции, объявлённые в namespace, не связываются при их определении без явного указания их неймспейса, а методы связываются. Теперь можно бегать и тыкать носом народ
#include <iostream>
using namespace std; // пёс с ним, это ideone подвёрстываетnamespace N
{
namespace M
{
void f();
}//ns M
}//ns Nusing namespace N;
void M::f() { cout<<"N::M::f"<<endl; } // пример (частично) квалифицированного имени свободной функцииusing namespace M;
int main() {
f();
M::f();
N::M::f();
return 0;
}