C++ primer:命名空间与多重继承

原创 2012年03月29日 19:46:17

1.库倾向于定义许多全局名字——主要是模板名、类型名或函数名。在使用来这些名字中有一些几乎不可避免地会发自多个供应商的库编写应用程序的时候,生冲突,这种名字冲突问题称为命名空间污染问题。

2.命名空间为防止名字冲突提供了更加可控的机制,个命名空间是一个作用域,通过在命名空间内部定义库中的名字,库的作者(以及用户)可以避免全局名字固有的限制。

3.命名空间定义以关键字 namespace 开始,后接命名空间的名字。命名空间可以在全局作用域或其他作用域内部定义,但不能在函数或类内部定义。

4.命名空间作用域不能以分号结束。

namespace cplusplus_primer {
class Sales_item { /* ... */};
Sales_item operator+(const Sales_item&,
const Sales_item&);
class Query {
public:
Query(const std::string&);
std::ostream &display(std::ostream&) const;
// ...
};
class Query_base { /* ... */};
}

5.命名空间外部的代码必须指出名字定义在哪个命名空间中:

cplusplus_primer::Query q =
cplusplus_primer::Query("hello");
q.display(cout);

6.像对 std 中定义的命名空间所做的那样,可以编写 using 声明(第 3.1 节)来获得对我们知道将经常使用的名字的直接访问:

using cplusplus_primer::Query;

7.一个命名空间的分离部分可以分散在多个文件中,在不同文本文件中的命名空间定义也是累积的。

8.定义在全局作用域的名字(在任意类、函数或命名空间外部声明的名字)是定义在全局命名空间中的。全局命名空间是隐式声明的,存在于每个程序中。

9.嵌套命名空间中的名字遵循常规规则:外围命名空间中声明的名字被嵌套命名空间中同一名字的声明所屏蔽。

10.未命名的命名空间与其他命名空间不同,未命名的命名空间的定义局部于特定文件,从不跨越多个文本文件。未命名的命名空间以关键字 namespace 开头,接在关键字 namespace 后面的是由花括号定界的声明块。

11.一个 using 声明一次只引入一个命名空间成员,从 using 声明点开始,直到包含 using 声明的作用域的末尾,名字都是可见的。

12.可用命名空间别名将较短的同义词与命名空间名字相关联

namespace primer = cplusplus_primer;

13.using 指示以关键字 using 开头,后接关键字 namespace,再接命名空间名字。.使得特定命名空间所有名字可见,没有限制。

14.可以尝试用 using 指示编写程序,但在使用多个库的时候,这样做会重新引入名字冲突的所有问题。

15.对命名空间内部使用的名字的查找遵循常规 C++ 查找规则:当查找名字的时候,通过外围作用域外查找。对命名空间内部使用的名字而言,外围作用域可能是一个或多个嵌套的命名空间,最终以全包围的全局命名空间结束。

namespace A {
int i;
namespace B {
int i;
// hides A::i within B
int j;
int f1()
{
int j;
// j is local to f1 and hides A::B::j
return i; // returns B::i
}
} // namespace B is closed and names in it are no longer visible
int f2() {
return j;
// error: j is not defined
}
int j = i;
// initialized from A::i
}

16.可以从函数的限定名推断出查找名字时所检查作用域的次序,限定名以相反次序指出被查找的作用域。限定符 A::C1::f3 指出了查找类作用域和命名空间作用域的相反次序,首先查找函数 f3 的作用域,然后查找外围类 C1 的作用域。在查找包含 f3 定义的作用之前,最后查找命名空间 A 的作用域。

17.接受类类型形参(或类类型指针及引用形参)的函数(包括重载操作符),以及与类本身定义在同一命名空间中的函数(包括重载操作符),在用类类型对象(或类类型的引用及指针)作为实参的时候是可见的。

std::string s;
// ok: calls std::getline(std::istream&, const std::string&)
getline(std::cin, s);

当编译器看到 getline 函数的使用getline(std::cin, s的时候,它在当前作用域,包含调用的作用域以及定义 cin 的类型和string 类型的命名空间中查找匹配的函数。因此,它在命名空间 std 中查找并找到由 string 类型定义的 getline 函数。

18.在多重继承下,派生类的对象包含每个基类的基类子对象,构造派生类型的对象包括构造和初始化所有基类子对象

class Bear : public ZooAnimal {};
class Panda : public Bear, public Endangered {};

19.构造函数调用次序既不受构造函数初始化列表中出现的基类的影响,也不受基类在构造函数初始化列表中的出现次序的影响。

20.基类构造函数按照基类构造函数在类派生列表中的出现次序调用。总是按构造函数运行的逆序调用析构函数

21.在单个基类情况下,派生类的指针或引用可以自动转换为基类的指针或引用,对于多重继承也是如此,派生类的指针或引用可以转换为其任意基类的指针或引用。

void print(const Bear&);
void highlight(const Endangered&);
ostream& operator<<(ostream&, const ZooAnimal&);
Panda ying_yang("ying_yang");// create a Panda object
print(ying_yang);// passes Panda as reference to Bear
highlight(ying_yang); // passes Panda as reference to Endangered
cout << ying_yang << endl; // passes Panda as reference to ZooAnimal

22.编译器不会试图根据派生类转换来区别基类间的转换,转换到每个基类都一样好。

void print(const Bear&);
void print(const Endangered&);

Panda ying_yang("ying_yang");
print(ying_yang);// error: ambiguous
23.像单继承一样,用基类的指针或引用只能访问基类中定义(或继承)的成员,不能访问派生类中引入的成员。

24.假定所有根基类都将它们的析构函数适当定义为虚函数,那么,无论通过哪种指针类型删除对象,虚析构函数的处理都是一致的:

25.当一个类有多个基类的时候,通过所有直接基类同时进行名字查找。多重继承的派生类有可能从两个或多个基类继承同名成员,对该成员不加限定的使用是二义性的,即使两个继承的函数有不同的形参表,也会产生错误。类似地,即使函数在一个类中是私有的而在另一个类中是公用或受保护的,也是错误的。。名字查找总是以两个步骤发生(第 7.8.1 节):首先编译器找到一个匹配的声明(导致二义性),然后,编译器才确定所找到的声明是否合法。

26.虚继承是一种机制,类通过虚继承指出它希望共享其虚基类的状态。在虚继承下,对给定虚基类,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象。共享的基类子对象称为虚基类

27.通过用关键字 virtual 修改声明,将基类指定为通过虚继承派生。

// the order of the keywords public and virtual is not significant
class Raccoon : public virtual ZooAnimal { /* ... */ };
class Bear : virtual public ZooAnimal { /* ... */ };

28.指定虚派生只影响从指定了虚基类的类派生的类。除了影响派生类自己的对象之外,它也是关于派生类与自己的未来派生类的关系的一个陈述。

29.可以无二义性地直接访问共享虚基类中的成员。同样,如果只沿一个派生路径重定义来自虚基类的成员,则可以直接访问该重定义成员。在非虚派生情况下,两种访问都可能是二义性的

1. 如果在每个路径中 X 表示同一虚基类成员,则没有二义性,因为共享该成员的单个实例。
2. 如果在某个路径中 X 是虚基类的成员,而在另一路径中 X 是后代派生类的成员,也没有二义性——特定派生类实例的优先级高于共享虚基类实例。
3. 如果沿每个继承路径 X 表示后代派生类的不同成员,则该成员的直接访问是二义性的。

30.通常,每个类只初始化自己的直接基类。在应用于虚基类的进修,这个初始化策略会失败。如果使用常规规则,就可能会多次初始化虚基类。为了解决这个重复初始化问题,在虚派生中,由最低层派生类的构造函数初始化虚基类。

31.无论虚基类出现在继承层次中任何地方,总是在构造非虚基类之前构造虚基类

php5增加的命名空间以及异常

1、命名空间 当我们加载很多文件的时候 (e.g. jia'azi)
  • fanyilong_v5
  • fanyilong_v5
  • 2014年04月24日 10:30
  • 1097

C++学习小疑问:类的名称能否和命名空间的名称相同?

对于类的名称能否和命名空间名称相同。我们可以看如下的实例: 定义命名空间和类名称相同: //name.h #pragma once namespace li { class li { public...
  • liyongqiang2420
  • liyongqiang2420
  • 2016年11月11日 17:03
  • 1305

php命名空间namespace自动载入

php的命名空间仅仅提供了一个逻辑上的类的隔离空间,我们在引用类时,仍要自己实现自动载入。思路就是使用一个未引入的类时,php自动触发spl_autoload_register这个方法,然后就会根据命...
  • u012371137
  • u012371137
  • 2016年07月22日 17:27
  • 2716

C++ premier -- 异常、命名空间以及多重继承

放了两个星期的暑假,回来久久不能进入状态。也或许是这一章对编程经验的要求远高于我目前的水平,很难静下心来看下去。总结也可能会因此做得很不到位。Anyway,有些东西就先记在这里吧。 第17章起就是高...
  • wolenski
  • wolenski
  • 2012年08月19日 14:57
  • 661

命名空间与多重继承

1.命名空间1.1 基本形式namespace ns{ /*...*/ } //没有";" 不能出现在函数或类的内部。 ::member_name表示...
  • zhanghuanzj
  • zhanghuanzj
  • 2016年03月05日 20:40
  • 215

Chapter 28.命名空间、多重继承和虚继承

命名空间 using声明 eg: using std::list;//推荐 using指示 eg: using namespace std; 防止命名空间污染,可不连续 eg: n...
  • vv_VV_vv
  • vv_VV_vv
  • 2012年12月26日 23:18
  • 401

多重继承《C++ primer 3th》

多重继承 《C++ primer 3th》P794~798 为支持多继承,一个类的派生表: class Bear : public ZooAnimal { ... }; 被扩展成支持逗号分割的基类表。...
  • huapenguag
  • huapenguag
  • 2016年02月18日 15:03
  • 335

C++ Primer 学习笔记_97_用来大型程序的工具 -多重继承与虚继承[续2]

用于大型程序的工具 --多重继承与虚继承[续2] 七、特殊的初始化语义 从具有虚基类的类继承的类对初始化进行特殊处理:在虚基类中,由最低层派生类的构造函数初始化虚基类。在ZooAnimal示例中...
  • u011744843
  • u011744843
  • 2016年05月12日 18:36
  • 338

C++ primer第二次阅读学习笔记(第17章:用于大型程序的工具:多重继承与虚继承) .

第十七章:用于大型程序的工具:多重继承与虚继承 多重继承是从多于一个直接基类派生类的能力。多重继承的派生类继承其所有父类的属性。 为了支持多重继承,应扩充派生列表,多个类用逗号分割。如: cla...
  • ithzhang
  • ithzhang
  • 2012年05月29日 20:09
  • 1600

C++ Primer学习笔记——$19 多重继承与虚继承

题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。  作者: tyc611,...
  • whycold
  • whycold
  • 2011年01月19日 15:13
  • 684
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ primer:命名空间与多重继承
举报原因:
原因补充:

(最多只允许输入30个字)