Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2341198
  • 博文数量: 816
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-17 17:57
文章分类

全部博文(816)

文章存档

2011年(1)

2008年(815)

分类:

2008-12-17 18:07:59

Namespaces and the ANSI/ISO C++
Standard Library

The namespace mechanism creates a collection of classes, free functions, constant declarations and so forth that
are qualified by a name. The syntax for a namespace declaration is:

namespace Name
{
  declaration and definitions of classes, functions,
  constants, etc.
}

In a program, the elements of a namespace are accessed by using the "::" operator. For instance, the namespace
MathConstants contains the definitions of two mathematical constants p and e. Access their value in the namespace
MathConstants using the syntax MathConstants::PI and MathConstants::E.

namespace MathConstants
{
  const double PI = 3.141592653589793;
  const double E = 2.718281828459045;
}

Namespaces permit the programmer to bundle a variety of C++ constructs in a named collection.

---------------------------------------------------
PROGRAM Namespaces-1 DECLARING AND USING NAMESPACES
---------------------------------------------------

This short program uses the namespace MathConstants and accesses the constants in the function main(). Assume
that the namespace declaration for MathConstants is stored in the header file "mconst.h".

#include
#include "mconst.h"
using namespace std;
int main()
{
  cout << setreal(1,8) << MathConstants::PI << endl
       << setreal(1,10) << MathConstants::E << endl;
  return 0;
}

Run:
3.14159265
2.7182818285

Duplicate Names
Two namespaces may contain elements with the same name. This can occur when you install two different software
packages that support classes, functions, or constant declarations that use the same names. For instance, consider
the two namespaces MathConstants and ShortConstants. The two namespaces provide constants of the same name
but with different precision.

namespace MathConstants
{
  const double PI = 3.141592653589793;
  const double E = 2.718281828459045;
}

namespace ShortConstants
{
  const double PI = 3.14159;
  const double E = 2.71828;
  const double ROOT2 = 1.41421;
}

A program references PI in MathConstants using the expression MathConstants::PI and PI in ShortConstants
using the expression ShortConstants::PI.

The Keyword using

The keyword using allows the elements of a single namespace to be referenced without the "::" operator. All
elements of any other namespace must use the "::" operator. The syntax for the keyword is

using namespace Name;

If the code provides the statement

using namespace MathConstants;

a program statement

cout << E << " " << ShortConstants::E
     << ShortConstants::ROOT2 << endl;

outputs the value of E from MathConstants. The references to a constants E and ROOT2 in the namespace
ShortConstants must use the "::" operator.
The C++ Standard Library
ANSI (American National Standards Institute) and ISO (International Standards Organization) cooperate to develop a
worldwide standard for the C++ language called the ANSI/ISO C++ Standard. This standard defines a C++ library
that includes the Standard Template Library (STL) of container classes and the string class. The library bundles the
components in a namespace called std. The C++ Standard library provides 32 C++ header files, as shown in Table
Namespaces1.

Table Namespaces1 C++ Library Header Files

            
                   
              
             
        
    
  

The Standard Library also includes 18 additional header files that describe the key facilities of the original library
supplied by the C programming language. The header files are provided in Table Namespaces2:

Table Namespaces2 C++ Header Files for C Library Facilities

  
  
  
    

To use the components of the standard C++ library, include the necessary header files and add the statement

using namespace std;

to the program. For instance, to use the I/O library and the string class, include the following statements:

#include // accesses I/O stream classes
#include // string class
using namespace std; // reference components without using std::

----------------------------------
PROGRAM ILLUSTRATING NAMESPACE STD
----------------------------------

This program declares the C++ string object str, inputs its value using the C++ stream I/O library, and outputs the
result.

#include
#include
#include

using namespace std;

int main()
{
  string first, last, fullname;
  double x;
  cout << "Enter a first and last name: ";
  // operations from the ANSI string class
  cin >> first >> last;
  fullname = last + ", " + first;
  cout << "The full name is " << fullname << endl;
  cout << "Enter a number: ";
  cin >> x;
  // sqrt() comes from
  cout << "The square root of " << x << " is "
       << sqrt(x) << endl;
  return 0;
}

Run:
Enter a first and last name: Standard Ansi
The full name is Ansi, Standard
Enter a number: 5
The square root of 5 is 2.23607

--------------------next---------------------
On C++ namespaces
by Tomas Restrepo

Introduction
Since it's creation by Bjarne Stroustrup, C++ has undergone extensive changes, specially in more recent years by the C++ Standards Committee. Several new features have been added to the basic language, including templates, exception handling, run time type information, and, of course, namespaces.

You might be inclined to believe that namespaces don't affect you one way or another unless you decide to use them, but they do. The C++ Standards Committee has basically rewritten the Standard Library, placing most of its facilities inside a namespace called std. This change alone forces changes in existing pre-draft programs that use the SL.

But, What's a namespace, really?
A namespace defines a new scope. Members of a namespace are said to have namespace scope. They provide a way to avoid name collisions (of variables, types, classes or functions) without some of the restrictions imposed by the use of classes, and without the inconvenience of handling nested classes.

Defining a namespace is similar to defining a class. First goes the namespace keyword, followed by the identifier (the namespace name), followed by member declarations enclosed in braces. For example:


namespace direct {
  class Arrow
  {
  public:
    Arrow(int dir);
    void  setDirection(int dir);
  private:
    int   direction;
  }
  // ...... other stuff
}

A namespace, however, cannot have access specifiers, such as public: or private:. All members of a namespace are public. It cannot have a trailing semicolon, either. An important difference between classes and namespaces, is that class definitions are said to be closed, meaning that, once defined, new members cannot be added to it. A namespace definition is open, and can be split over several units. For example:


// file SY.h
namespace SY {
  class Maker { ... };
  class SuperMaker : public Maker { ... };
}

// file  data.h
namespace SY {
  class Binder { ... };
  class DataBinder : public Binder { ... };
}
In this example, there are two files (SY.h and data.h), both defining namespace SY. The definition of SY on data.h does not conflict with the one in SY.h, but actually extends it. If you look closely at the Standard Library, you'll notice that no single header file declares all members of namespace std. Each file only declares some members, adding them to the global std namespace.

Using Namespaces
There are four ways you can refer to namespace members:

Using the full member name, including the namespace it belongs to. For example:

  std::cout << "Hello Nasty";
Note: Remember that on Pre-Draft days, cout was not declared in any namespace (they didn't exist yet, anyway), and header files used an .h suffix.
By taking advantage of Using-Declarations, as in

  using std::cout;
  cout << "Hello Nasty";
this declares cout in the current scope as synonym for std::cout.
By taking advantage of Using-Directives, as in

  using namespace std;
  cout << "Hello Nasty";
which specifies that the current scope can refer to names in the std namespace without using full qualifiers. This is mostly used when porting legacy code.
Using aliases. Say, for example, I have

  namespace X
  {
    namespace Y
    {
      class Z { ... };
    }
  }
The full qualifier for Z is X::Y::Z, but we can declare an alias using

  namespace w = X::Y;
This declares w as an alias for namespace X::Y, thus we can access Z using w::Z.
Note: As you can see, namespaces can be nested. One of the design goals of namespaces was to encourage programmers and vendors to wrap their libraries inside them, minimizing name collisions. One particularly useful way of taking advantage of this is when you are designing libraries for, say, your company, which involve several pieces of functionality. For example, I keep some of my reusable system classes and templates in a WRuntime namespace, which contains different namespaces inside it like WThreading and WLogging.
Unnamed Namespaces
Until now, I've only covered named namespaces, but you can also declare unnamed namespaces. Take for example:


  namespace
  {
    class Car
    {
      .... // class members here
    }
    // other members here
  }
this definition behaves exactly like:


  namespace __UniqueName__
  {
    class Car
    {
      .... // class members here
    }
    // other members here
  }
 
  using namespace __UniqueName__;
For each unnamed namespace, the compiler generates a unique name (represented here by __UniqueName__), which differs from every other name in the program. You might be asking yourself, What's the use of this?

Let's see the example above. Class Car is defined in an unnamed namespace declared at global scope, thus, it can be referred to as if it were declared directly at global scope. However, since it's a member of an unnamed namespace, the compiler mangles its name with the generated namespace name, so it won't conflict with other names.

Unnamed namespaces can also be defined inside other namespaces. Suppose the unnamed namespace in the example above was declared inside namespace foo. Then class Car could be referred to as foo::Car. Notice there's no mention of the unnamed namespace, but the link name for Car will still be mangled with namespace foo and the unique name generated for the unnamed namespace by the compiler.

An interesting use of unnamed namespaces is hiding names inside modules. Before, this would be done using the static keyword, but the new C++ Standard reads in section 7.3.1.1 Unnamed Spaces, paragraph 2:

"The use of the static keyword is deprecated when declaring objects in a namespace scope, the unnamed namespace provides a superior alternative."
In case you've forgotten (or didn't know), static, when applied at namespace scope, specifies internal linkage. However, static only applies to names of objects, functions and anonymous unions, not to type declarations.

Personally, I feel that, while unnamed namespaces are a far better solution than static to this problem, it's not the best that could have been implemented. To me, using unnamed namespaces in this way seem to be too much like taking advantage of a "side" effect of the lack of name of the namespace. I would feel much more comfortable with an appropriately named keyword to accomplish this behavior (think hidden or internal), but then again, I'm no language lawyer, nor am I completely informed of the reasons why the committee chose it that way.

Conclusion
Namespaces are a powerful addition to an already powerful language, giving the programmer more flexibility, provided he knows how to take advantage of it. Please consider the use of namespaces carefully when planning your next project, you might be surprised at how useful they can be.

--------------------next---------------------

阅读(1194) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~