的实现。
使用我们的库的程序可以包含需要的头文件,那些头文件中的名字定义在命名空间 cplusplus_primer内部:
// --- main.cpp ---
#include "Sales_item.h"
int main()
{
cplusplus_primer::Sales_item trans1,trans2;
//...
}
6、定义命名空间成员
在命名空间内部定义的函数可以使用同一命名空间中定义的名字的简写形式:
namespace cplusplus_primer
{
std::istream &operator>>(std::istream &in,Sales_item &)
{
//...
return in;
}
}
在命名空间的外部定义命名空间成员:名字的命名空间声明必须在作用域中,并且定义必须指定该名字所属的命名空间:
cplusplus_primer::Sales_item
cplusplus_primer::operator+(const Sales_item &lhs,
const Sales_item &rhs)
{
Sales_item ret(lhs);
//...
return ret;
}
定义看起来类似于定义在类外部的类成员函数,返回类型和函数名由命名空间名字限定。一旦看到完全限定的函数名,就处于命名空间的作用域中。因此,形参表和函数体中的命名空间成员引用可以使用非限定名引用Sales_item。
7、不能在不相关的命名空间中定义成员
虽然可以在命名空间定义的外部定义命名空间成员,对这个定义可以出现的地方仍有些限制:只有包围成员声明的命名空间可以包含成员的定义。例如,operator+ 既可以定义在命名空间cplusplus_primer中,也可以定义在全局作用域中,但它不能定义在不相关的命名空间中。
8、全局命名空间
定义在全局作用域的名字(在任意类、函数或命名空间外部声明的名字)是定义在全局命名空间中的。全局命名空间是隐式声明的,存在于每个程序中。在全局作用域定义实体的每个文件将那些名字加到全局命名空间。
可以用作用域操作符引用全局命名空间的成员。因为全局命名空间是隐含的,它没有名字,所以记号
::member_name;
引用全局命名空间的成员。
//P603 习题17.13/14/15
//--- Bookstore.h ---
#ifndef BOOKSTORE_H_INCLUDED
#define BOOKSTORE_H_INCLUDED
#include
#include
#include
namespace Bookstore { class out_of_stock : public std::runtime_error { public: out_of_stock(const std::string &s): runtime_error(s) {} }; class isbn_mismatch : public std::logic_error { public: isbn_mismatch(const std::string &s):logic_error(s) {} isbn_mismatch(const std::string &s, const std::string &lhs, const std::string &rhs): logic_error(s),left(lhs),right(rhs) {} std::string left,right; virtual ~isbn_mismatch() throw () {} }; class Sales_item { friend Sales_item operator+(const Sales_item &,const Sales_item &); friend std::ostream &operator<<(std::ostream &,const Sales_item &); friend std::istream &operator>>(std::istream &,Sales_item &); public: Sales_item(const std::string &s = ""): isbn(s),units_sold(0),revenue(0) {} Sales_item(std::istream &in) { in >> *this; } std::string book() const { return isbn; } bool same_isbn(const Sales_item &rhs) const { return isbn == rhs.isbn; } void setVal() { std::cin >> isbn >> units_sold >> revenue; } Sales_item &operator+=(const Sales_item &rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } private: std::string isbn; unsigned units_sold; double revenue; }; } #endif // BOOKSTORE_H_INCLUDED
// --- Bookstore.cpp ---
#include "Bookstore.h"
namespace Bookstore
{
Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs)
{
if (!lhs.same_isbn(rhs))
{
throw isbn_mismatch("isbn mismatch ",lhs.book(),rhs.book());
}
Sales_item ret(lhs);
ret += rhs;
return ret;
}
std::ostream &operator<<(std::ostream &os,const Sales_item &rhs)
{
os << rhs.book() << "\t" << rhs.units_sold << "\t" << rhs.revenue;
return os;
}
std::istream &operator>>(std::istream &in,Sales_item &rhs)
{
double price;
in >> rhs.isbn >> rhs.units_sold >> price;
if (in)
{
rhs.revenue = price * rhs.units_sold;
}
else
{
rhs = Sales_item();
}
return in;
}
}
//--- MyApp.h ---
#ifndef MYAPP_H_INCLUDED
#define MYAPP_H_INCLUDED
#include "Bookstore.h"
namespace MyApp
{
void processTrans()
{
Bookstore::Sales_item item1,item2,sum;
while (std::cin >> item1 >> item2)
{
try
{
sum = item1 + item2;
}
catch (Bookstore::isbn_mismatch &e)
{
std::cerr << e.what() << ": left isbn(" << e.left
<< "); right isbn(" << e.right << ")" << std::endl;
continue;
}
std::cout << sum << std::endl;
}
}
}
#endif // MYAPP_H_INCLUDED