Suppose I have the following defined in a header file:
namespace MyNamespace
{
Class global_c;
}
Then I do this in a source file:
namespace MyNamespace
{
void MyClass::Function( )
{
::global_c.DoSomething( );
}
}
global_c turns out as undefined by the compiler, if I do just global_c.DoSomething( ); however it compiles fine, if I add 'using namespace MyNamespace;' to the top of the file it also works fine.
Since global_c lives in the same namespace as 'MyClass' why can't it be resolved just because '::' is added to the front of it?
Because you are explicitly telling the compiler to use the global namespace by prepending the variable with ::. As global_c does not exist in the global namespace it throws an error.
The compiler is just doing what you told it to do. Think of :: as Global::.
Related
I have a common_module.h file which should store structures and functions used by most of .cpp files.
I want it to have an RColor struct.
RColor uses a lot of functions and variables from namespace cv. The project is made in a way that .cpp files generally do not use cv namespace (All work with it is mostly done by structures like RColor)
I don't want to always write cv::something in definition of RColor. So i tried to create an RColor prototype in common_module.h and put it definition to Rcolor.cpp:
//common_module.h
//...
struct RColor;
#include "stdafx.h"
#include<opencv2/opencv.hpp>
using namespace cv;
struct RColor
{
...
};
//Project0.cpp (main file)
#include "stdafx.h"
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<windows.h>
RColor col;
I get error:
1>error C2079: 'col' uses undefined struct 'RColor'
You're getting the error because code using RColor needs to see its definition, not just its declaration. You'll have to move the definition to the header.
As to how to deal with the namespace cv, you write:
I don't want to always write cv::something in definition of RColor.
The correct response to this is "don't be lazy, write it." Explicit qualification is good, that's what namespaces are for. At least in the class definition itself, you have no way around it(*) - you want to prevent the identifiers from cv from polluting the global namespace. Note that it also makes the code more self-documenting: cv::transform tells a reader way more about the type or function than just transform does (is the latter cv::transform or std::transform or ...?)
If you really want and need to save on typing cv:: inside member functions of RColor, you can put using namespace cv; inside the member function definitions. But I wouldn't do even that.
(*) There is actually a way to achieve what you want, but it's quite hacky (and would never pass code review with me). But out of a sense of completeness, here goes:
// common_module.h
namespace NobodyTryToUseThisName
{
using namespace cv;
struct RColor
{
// ... definition here
};
}
using NobodyTryToUseThisName::RColor;
But as I say, I do not recommend doing this.
I'm working on a project in c++ and I stuck with no idea what is wrong. I've writen 4 classes and everything looked fine during work (under visual studio 2010). VS 'saw' all the definition, i could use auto-fill and sudgestions, but when I tried to compile the project it sudennly went blind. It's like I didnt include headers or something (which I did). The strange thing is there is no problem with working with those classes on VS (i can ctrl+space for hint, list of attributes and methods and all that stuff) but when i try to compile it says "ClassName" is not a type.
Quick sample of problem below:
ProButton.cpp:
#include "ProButton.h"
using namespace pGUI;
ProButton::ProButton( ... )
: ProControl( ... )
{
...
}
ProButton.h:
#ifndef __PRO_BUTTON__
#define __PRO_BUTTON__
#include <string>
#include "ProControl.h"
namespace pGUI
{
class ProButton :
public pGUI::ProControl
{
public:
//attributes
...
public:
//methods
...
};
}
#endif
but compiler says:
Error 291 error C2653: 'ProButton' : is not a class or namespace name
for this line in ProButton.cpp: ProButton::ProButton( ... )
It also says:
Error 23 error C2039: 'ProControl' : is not a member of 'pGUI'
Error 24 error C2504: 'ProControl' : base class undefined
and all similar errors for whole project. I have no idea what is wrong. Looks like my VS broke :D
Of course those (...) means there is code there, just not that important for now. I can upload all solution somewhere fi it will help.
edit//
About namespaces, all header files (classes declaration) are defined in namespace with:
namespace pGUI{
class ProClass
{
};
}
all definitions for these classes (in ProClass.cpp) are using:
using namespace pGUI;
at the beginning.
I think the problem is with order of including files.
Im not sure how this is supposed to be done. So far i have 4 classes that:
class ProGUI:
has a pointer to ProContainer
includes: ProContainer and ProControl
class ProContainer:
has pointers to: ProGUI and ProControl
class ProControl:
has a pointer to ProContainer
includes ProButton
is a base class for ProButton
class ProButton:
is a sub-class of ProControl
Those classes also uses irrlicht library and I'm not sure where to include it.
I had it included in my main file just before #include "ProGUI.h". This is also the only include in main. ProGUI.h .
//EDIT 2 -> solved
It was a problem with includes. I needed to rethink my inclusion order and add some forward declarations. Anyway that all seemed strange and took me a lot of time to figure i out. Thx for help. :)
It seems that you are using following statement:
using namespace pGUI;
Just before the class declaration:
class ProControl
{
};
Instead of using following approach:
namespace pGUI
{
class ProControl
{
};
}
The using namespace, as it says uses a namespace. You need to explicitly put something a namespace using namespace keyword followed by braces!
using namespace pGUI informs the compiler that it should look in the pGUI namespace to resolve existing names.
To declare or implement something in a namespace you need to be more specific. with either:
namespace pGUI
{
ProButton::ProButton( ... ) : ProControl( ... )
{
...
}
}
or:
pGUI::ProButton::ProButton( ... ) : ProControl( ... )
{
....
}
Personally, I consider any use of using namespace to be a lazy programmer hack that completely defeats the point of namespaces. But I digress. :)
I found a problem concerning namespace search.
The following simplified code failed to compile:
namespace A {
namespace B {
class Test {
};
}
namespace C {
namespace B {
typedef B::Test AnAlias;
}
}
}
The compiler complains that Test in namespace A::C::B does not name a type.
The problem seems to be that the compiler sees a namespace B inside namespace C and does not no further search. I would have exspected that he also would look in namespace A (which is a enclosing namespace) and find the B::Test there.
If I rename C::B everything is fine.
If I qualify A::B::Test everything is fine.
If I put the typedef directly in namespace A::C everything is fine.
This behavior was tested with gcc 4.1 and intel 12 compiler. (both for linux).
Are the compilers right?
The B in typdef B::Test resolves to A::C::B. If you're going to reuse the name B, you need to specify it to remove the ambiguity. The compilers are behaving properly. IIRC, names are resolved to the closest declaration to its use or reference. In this case A::C::B is the closest declaration to the typedef.
Could somebody tell me what is the difference between
using namespace android;
....
and
namespace android {
....
}
I found that almost all .cpp files in Android source code use the second one.
Also, If I want to include some files that use the type of second one in my own project, do I need to use namespace android{...} too?
Because if I do not, compiler would report error when I call methods of included files. Or do I need to add any prefix before method call?
namespace android {
extern int i; // declare here but define somewhere
void foo ();
}
-- is used for scoping variables and functions inside a particular name. While using/calling those variables/functions, use scope resolution operator ::. e.g.
int main ()
{
android::foo();
}
There is no restriction for putting all namespace declarations in a single body instance. Multiple namespace android bodies spread across several files, is possible and also recommended sometimes. e.g.
// x.cpp
namespace android {
void somefunc_1 ();
}
// y.cpp
namespace android {
void somefunc_2 ();
}
Now, sometimes you may find using :: operator inconvenient if used frequently, which makes the names unnecessarily longer. At that time using namespace directive can be used.
This using directive can be used in function scope / namespace scope / global scope; But not allowed in class scope: Why "using namespace X;" is not allowed inside class/struct level?).
int main ()
{
using namespace android;
foo(); // ok
}
void bar ()
{
foo(); // error! 'foo' is not visible; must access as 'android::foo()'
}
BTW, Had using namespace android; declared globally (i.e. above main()), then foo() can be accessed without :: in Bar() also.
My answer is probably only helpful if you are more experienced with Java. I'm guessing since you are doing android stuff that this is the case.
The following means that you are declaring a class called MyClass in the namespace android. The qualified name of the class would be android::MyClass.
namespace android {
class MyClass {...};
}
It can be thought of similarly to the Java code:
package android;
public class MyClass {...}
The following means that you can use classes, functions etc. defined in the android namespace without having to use their qualified name (assuming they have been included).
using namespace android;
This
#include <path/to/MyClass.h>
using namespace android;
can be thought of similarly to the Java code:
import android.MyClass;
I expected to be able to use a namespace alias in a class declaration but get a compiler syntax error.
struct MyClass
{
namespace abc = a_big_namespace;
void fn() {
abc::test();
}
};
The only way I can get it to work is to put the alias in every function.
void fn() {
namespace abc = a_big_namespace;
abc::test();
}
Additionally I would like to be able to use the alias for function parameters. I haven't found a work-around for that.
void fn(abc::testType tt) {
abc::test(tt);
}
Is there a way to do what I want?
EDIT: my solution
I found that I didn't need unnamed namespace for my particular problem and can simply do this:
namespace myspace
{
namespace abc = a_big_namespace;
struct MyClass
{
void fn(abc::testType tt) {
abc::test(tt);
}
};
}
To switch to the other library, which is what my alias namespace refers to I just change the alias. This method even allows me to have the same class in a single file twice, each time refering to a different library.
Thanks for all your help.
Namespace alias in the class definition is illegal, as specified by the language specification.
Its allowed in only in namespace scope or function scope.
You can make alias at namespace scope. But that will be make permanent alias which can be used from other files as well. But the solution is simple : you can use unnamed namespace to prevent alias (and therefore all symbols from the big namespace) from being visible from other files. This is how it can be done:
//MyFile.cpp
namespace myspace
{
namespace //this is unnamed namespace
{
namespace abc = a_big_namespace;
}
struct MyClass
{
void fn()
{
abc::test(); //don't worry, this will work!
}
};
}
//OtherFile.cpp
myspace::abc::test(); //error - that means, prevention worked.
The alias is not visible from other files. When compiling OtherFile.cpp, GCC (4.5.0) says,
'myspace::abc' has not been declared
That proves the alias abc is visible only in MyFile.cpp. Thanks to unnamed namespace.
Demo : http://www.ideone.com/2zyNI (though it doesn't demonstrate OtherFile concept. I cannot have more than one file at ideone.com)
The scope of a namespace alias is a code block.
So you can put it in any code block.
BUT, you can't put it inside a class, because that will mean it's a member of the class.
A namespace alias can't be a member.
More about namespace aliases:
What is the scope of a namespace alias in C++?
Namespaces
It works if you declare the alias outside of the struct.
You can of course also put the alias outside the class:
namespace abc = a_big_namespace;
struct MyClass {
void fn()
{ abc::test(); }
};