C++ Knowledge series Layering

Programming has its own methodology.

Layering is everywhere in real life,this why the pruchase and sale exist.

Layering, Insert additional indirection

 

  1. 通过分层layering/add indirection来体现 "有一个" 或 "用...来实现’ composition /composite
  2. 使某个类的对象成为另一个类的数据成员,从而实现将一个类构筑在另一个类之上,这一过程称为 "分层"(Layering). 
  3. User GUI  Application Layer  Domain Layer (Business Logical Tier)  Infrastructure Layer (OS, DB tier).
  4. A little difference from the private inheritance which also means a kind of has-a or use-implementation relationship.
  5. 当通过分层使两个类产生联系时,实际上在两个类之间建立了编译时的依赖关系dependent。Separate implementation from interface, decouple, decompose.  Composition
  6. 区分继承inheritance和模板template. 涉及到"类的行为"behavior of class 和 "类所操作的对象的类型"之间的关系。
  7. Behavior of class and type of being operated
  8. 当对象的类型不影响affect/reflect类中函数的行为behaviour/behavior时,就要使用模板来生成这样一组类。
  9. 当对象的类型影响类中函数的行为时,就要使用继承来得到这样一组类。
  10. 私有继承的含义不是 "是一个"。Has-a or use-implementation
  11. 关于私有继承的第一个规则rule正如你现在所看到的:和公有继承相反,如果两个类之间的继承关系为私有,编译器一般不会将派生类对象(如Student)转换成基类对象(如Person)。第二个规则是,从私有基类继承而来的成员都成为了派生类的私有成员,即使它们在基类中是保护或公有成员。行为特征character就这些。
  12. 私有继承意味着 "用...来实现"。如果使类D私有继承于类B,这样做是因为你想利用类B中已经存在的某些代码,而不是因为类型B的对象和类型D的对象之间有什么概念上的关系。因而,私有继承纯粹是一种实现技术technique。私有继承意味着只是继承实现,接口会被忽略。如果D私有继承于B,就是说D对象在实现中用到了B对象,仅此而已。私有继承在软件 "设计" design过程中毫无意义meaningless/insignificant,只是在软件 "实现" 时才有用。
  13. private inheritance, private or protected new, delete, constructor, destructor, friend class, all of these can be as trick when coding.
  14. 模板template是C++最有用useful的组成部分之一,但一旦开始经常性地使用它,你会发现,如果实例化一个模板一百次,你就可能实例化了那个模板的代码一百次。模板导致的 "代码膨胀"extension of code。
  15. 有时私有继承是表达类之间 "用...来实现" 关系的唯一有效effective途径。所以,当私有继承是你可以使用的最合适的实现方法时,就要大胆地boldly使用它。同时,广泛意义上来说,far and wide/widely/ by and large分层是应该优先采用的技术,所以只要有可能,就要尽量使用它。
  16. 如果一个派生类从多个基类继承了一个成员名,所有对这个名字的访问都是二义ambiguity的;你必须明确地说出你所指的是哪个成员。
  17. 这是一个集纯虚函数,简单虚函数和内联函数,综合应用之大成的方法,值得牢记在心。引入introduce/import新类 加入一个间接层。Indirect layer
  18. 如果真的将A声明为B和C的虚基类 virtual base class which is apparent only once within hierarchy structure,往往会在间和时间上强加给用户额外的开销extra cost。因为虚基类常常是通过对象指针来实现的 implemented by the pointer to object of class,并非对象本身。自不必说,内存中对象的分布layout/distribution是和编译器compiler相关的,但一条不变的事实是:如果A作为 "非虚" 基类,类型D的对象在内存中的分布通常占用连续的continual/consecutive内存单元;如果A作为 "虚" 基类,有时,类型D的对象在内存中的分布占用连续的内存单元,但其中两个单元unit包含的是指针,指向包含虚基类数据成员的内存单元。
  19. 一个空类void /empty class什么时候不是空类? ---- 当C++编译器通过它的时候。如果你没有声明下列函数,体贴的considerate编译器会声明它自己的版本where needed。这些函数是:一个拷贝构造函数copy constructor,一个赋值运算符assignment operator,一个析构函数destructor,一对取址运算符address-of operator。另外,如果你没有声明任何构造函数constructor,它也将为你声明一个缺省构造函数。所有这些函数都是公有的。  If a class is empty, there is in fact a char[1] in the class.
  20. const CString& operator=(const CString& stringSrc);
  21. Empty* operator&(); //for ordinary object
  22. const Empty* operator&() const;//for const object
  23. 生成的析构函数一般是非虚拟的,除非它所在的类是从一个声明了虚析构函数的基类继承而来。
  24. 缺省拷贝构造函数(赋值运算符)对类的非静态数据成员进行 "以成员为单位的memberwise" 逐一拷贝构造(赋值)
  25. 声明了至少一个构造函数constructor with some parameter but not itself as parameter,编译器将不会生成缺省构造函数。
  26. 面对这样的难题,C++拒绝编译这段代码。如果想让一个包含引用成员reference member or pointer 的类支持赋值,你就得自己定义赋值运算符。对于包含const成员的类(例如上面被修改的类中的objectValue)来说,编译器的处理也相似;因为修改const成员是不合法的,所以编译器在隐式生成赋值函数时也会不知道怎么办。还有,如果派生类的基类将标准赋值运算符声明为private,  编译器也将拒绝decline为这个派生类生成赋值运算符。因为,编译器为派生类生成的赋值运算符也应该处理基类部分,但这样做的话,就得调用对派生类来说无权访问的基类成员函数,这当然是不可能的。Make impossibility possible.
  27. 这是因为,确定非局部静态对象初始化的 " 正确" 顺序order很困难,非常困难,极其困难。即使在它最普通的形式下 ---- 多个被编译单元,多个通过隐式模板实例化所生成的非局部静态对象(隐式implicitly模板实例化时,它们本身可能都会产生这样的问题) ---- 不仅不可能确定正确的初始化顺序,往往连找一个可以确定正确顺序的特殊情况都不值得。
  28. 虽然关于 "非局部"non-local static object 静态对象什么时候被初始化,C++几乎没有做过说明;但对于函数中的静态对象(即,"局部" local static object静态对象)什么时候被初始化,C++却明确指出:它们在函数调用过程中初次碰到对象的定义时被初始化。所以,如果你不对非局部静态对象直接访问,而用返回局部静态对象引用的函数调用来代替,就能保证从函数得到的引用指向的是被初始化了的对象。这样做的另一个好处是,如果这个模拟非局部静态对象的函数从没有被调用,也就永远不会带来对象构造和销毁destroy的开销cost;而对于非局部静态对象来说就没有这样的好事。
  29. 这种返回引用reference return的函数虽然采用了上面所讨论的技术,但函数本身总是很简单:第一行定义并初始化initialize一个局部静态对象,第二行返回它,仅此而已。你可能很想把它声明为inline。条款33指出,对于C++语言规范的最新修订版本来说,这是一个非常有效的实现策略strategy/policy;但它同时指出,在使用之前,一定要确认你的编译器和标准中的相关要求要一致consistent。如果编译器不符合最新标准standard,你又象上面那样使用内联inline,就可能造成函数以及函数内部静态对象有多份拷贝 copy。这足以让一个成年的程序员哭泣. More copy of static object will be caused/brought about if the function within static object is defined as inline function.
  30. C++中有很多 "东西":C,重载overload(function with the same name but with the different parameter),覆盖override,面向对象Object-oriented,模板template,例外exception,名字空间namespace, abstract encapsulation inheritance polymorphism /composition
  31. 和传统开发工具及环境的兼容性compatibility。各色不同的开发环境到处都是,编译器compiler、链接器linker和编辑器editer则无处不在
  32. 解决真实actual/real/factual/the de facto问题的可应用性applicability。C++没有被设计为一种完美的perfect,纯粹的pure语言,不适于用它来教学生如何编程。它是设计为专业程序员的强大工具,用它来解决各种领域domain中的真实问题。
  33. 为什么隐式implicitly生成的拷贝构造函数和赋值运算符要象现在这样工作呢,尤其是指针(参见条款11和45)?因为这是C对struct进行拷贝和赋值的方式,和C兼容compatible很重要。
  34. 为什么析构函数不自动automatically被声明为virtual,为什么实现细节必须出现在类的定义definition中因为不这样做就会带来性能上capability/performance的损失,效率efficiency /performance很重要。
  35. 为什么C++不能检测非局部静态对象之间的初始化依赖关系dependent relationship呢?因为C++支持单独编译(即,分开编译源模块,然后将多个目标文件链接起来,形成可执行程序),依赖现有的链接器,不和程序数据库打交道。所以,C++编译器几乎不可能知道整个程序的一切情况。
  36. The Design and Evolution of C++.  D&E == Design and Evolution
  37. 一个虚函数调用所使用的缺省参数default argument是表示对象的指针或引用的静态类型static type所决定的虚函数所声明的缺省参数。派生类中的重载函数不获取它重载的函数中的缺省值default value。
  38. International Standard for Information Systems----Programming Language C++. International Organization for Standardization (ISO)。
  39. 如果在 "D&E千里之外的视野" 和 "C++标准的微观世界" 之间存在承上启下的桥梁那就太好了。Beyond
  40. The Annotated C++ Reference Manual
  41. 所以,为了防患于未然,Stroustrup决定让派生类成员按名字隐藏掉hide所有得重载的基类成员 override all overloaded functions in base class,也无论是普通函数还是虚拟函数。No matter whether the member function is normal or virtual. Names in base are hidden by names in derived. 如果想使用基类被override的函数,可以采取using Base::function(),或者另写一个虚拟函数调用基类成员函数。

 

posted @ 2013-08-05 10:45  iDragon  阅读(239)  评论(0编辑  收藏  举报