2013-3-21
下面主要说3点:
1. 如何使一个目录变成包,如何import
目录下放一个__init__.py文件(内容可以为空), import包内模块的时候使用"."分割, 比如import Apackage.Amodule
2. __init__.py的__all__变量
__all__指定的是指此包被import * 的时候, 哪些模块会被import进来
3. __init__.py的__path__变量
__path__指定了包的搜索路径
__all__ = ['module_13', 'module_12']
rom package1.subPack1 import * 只会导入module_12 13文件
(3) 如果根本不知道文件所在目录,就需要在根目录下进行查找(查找整个硬盘空间),但是由于根目录下某些文件(bin、sbin、boot、dev、initrd、lib)没有查找价值,因而要将其排除在查找范围之外
# cd /
grep -rin findcontents `ls | grep -vE 'bin|boot|dev|initrd|lib'`
用户定义一个empty class (空类),当C++ 处理过它之后,如果你自己没声明,编译器就会为它声明(编译器版本的)一个copy 构造函数、一个copy assignment操作符和一个析构函数。此外如果你没有声明任何构造函数,编译器也会为你声明一个default 构造函数。所有这些函数都是public 且inline 。
class Empty { };
这就好像你写下这样的代码:
class Empty { public: Empty() { ... } Empty(const Empty& rhs) { ... ) -Empty( ) { ... } Empty& operator=(const Empty& rhs) { ... } };
某些对象是独一无二的(比如房子),你应该禁用copy 构造函数或copy assignment 操作符,可选的方案有两种
(1)定义一个公共基类 privaate copying函数
(2) 创建一个宏,并将之放到每一个独一无二对象的private中,该宏为:
// 禁止使用拷贝构造函数和 operator= 赋值操作的宏 // 应该类的 private: 中使用 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&)
这种方法比第一种方法好,google C++编程规范中提倡使用该方法。
条款07: 为多态基类声明virtual 析构函数
本条款阐述了一个程序员易犯的可能导致内存泄漏的错误,总结了两个程序员应遵守的百编程原则:
(1)polymorphic (带多态性质的) base classes 应该声明一个virtual 析构函数。如果
class 带有任何virtual 函数,它就应该拥有一个virtual 析构函数。这样,但用户delete基类指针时,会自动调用派生类的析构函数(而不是只调用基类的析构函数)。
(2)Classes 的设计目的如果不是作为base classes 使用,或不是为了具备多态性(polymorphically) ,就不该声明virtual 析构函数。这是因为,当用户将一个函数声明为virtual时,C++编译器会创建虚函数表以完成动态绑定功能,这将带来时间和空间上的花销。
[1] const_cast<T>(expression) : 移除变量的const属性
[2] dynamic_cast<T>(expression) : 安全向下转型,即:基类指针/引用到派生类指针/引用的转换。如果源和目标类型没有继承/被继承关系,编译器会报错;否则必须在代码里判断返回值是否为NULL来确认转换是否成功。
[3] reinterpret_cast<T>(expression):底层转换
[4] static_cast<T>(expression):强迫隐式转换,如,将non-const对象转换为const对象,将int转换为double类型。
在C++继承中,virtual函数是动态绑定的,调用的函数跟指针或者引用实际绑定的那个对象有关,而non-virtual函数是静态绑定的,调用的函数只跟声明的指针或者引用的类型相关。
指针和引用只知道自己类型的相关信息!!
class B{ public: void func(){ cout<<“B”;} }; class D:public B{ public void func() { cout<<“D”;} };
下面是对B和D的使用:
D dObject; B* basePtr = &dObject; D* dOjbectPtr = &dObject;
看下面这两种调用方式:
basePtr->func(); dOjbectPtr->func();
你会发现打印结果为:
B
D
(1) 如果class之间的继承关系是private。编译器不会自动将一个derived class对象转化为一个base class对象。由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原来是protected或public属性。
线程池模式一般分为两种:L/F领导者与跟随者模式、HS/HA半同步/半异步模式。
HS/HA 半同步/ 半异步模式 :分为三层,同步层、队列层、异步层,又称为生产者消费者模式,主线程处理I/O事件并解析然后再往队列丢数据,然后消费者读出数据进行应用逻辑处理;
优点:简化编程将低层的异步I/O和高层同步应用服务分离,且没有降低低层服务性能。集中层间通信。
缺点:需要线程间传输数据,因此而带来的动态内存分配,数据拷贝,语境切换带来开销。高层服务不可能从底层异步服务效率中获益。
L/F 领导者跟随者模式
:在LF线程池中,线程可处在3种线程状态之一:
leader、follower或processor。处于leader状态的线程负责监听网络端口,当有消息到达时,该线程负责消息分离,并从处于
follower状态中的线程中按照某种机制如FIFO或基于优先级等选出一个来当新的leader,然后将自己设置为processor状态去分配和处
理该事件。处理完毕后线程将自身的状态设置为follower状态去等待重新成为leader。在整个线程池中同一时刻只有一个线程可以处于leader
状态,这保证了同一事件不会被多个线程重复处理。
缺点:实现复杂性和缺乏灵活性;
优点:增强了CPU高速缓存相似性,消除了动态内存分配和线程间的数据交换。