一些无关紧要的好奇
来源:互联网 发布:网络语狗子是啥意思 编辑:程序博客网 时间:2024/04/29 16:04
此文 来自BS个人主页 http://www.stroustrup.com/bsfaqcn.html
1、普通类有什么用处?
类是思想和观念的代码形式。类的对象数是思想的具体实例在代码上的体现。没有类,读代码的人只能猜测数据和函数的关系——类能清楚的表明这种关系,并且能被编译器理解。有了类,程序的高层结构就更能反映在代码上,而不单单是在注释中。
一个设计良好的类能为用户提供简洁易用的接口,并将其内部结构隐藏起来,用户根本不必了解其内部结构。如果内部结构不应该被隐藏——例如,因为用户需要随意改变类中的任何数据成员——你可以把这种类认为是“普通的老式的数据结构(data structure)”;例如:
struct Pair {Pair(const string& n, const string& v) : name(n), value(v) { }string name, value;};代码巨丑格式
注意,数据结构也可以使用辅助函数,例如构造函数。
设计类时,思考类有哪些方面在任何时刻对其每个对象都是通用的,这会很有用。这种通用的属性被称之为不变要素(invariant)。例如,vector的不变要素是,其内部有一个指针,指向一系列元素,这些元素的数目保存于一个整型变量。每个构造函数都有责任去构建类的不变要素,这样成员函数才能依赖这些不变要。成员函数退出时必须保持这些不变要素的有效性。这种思维方式对于管理资源的类来说更是特别有益,如管理锁(locks)、sockets和文件的类。例如,一个处理文件的类的不变要素是,它有一个指针,指向一个打开的文件。该类的构造函数负责打开文件,而其析构函数负责释放构造函数获取的资源。例如,该类的析构函数负责关闭构造函数打开的文件:
class File_handle { public: File_handle(const char* n, const char* rw) { f = fopen(n,rw); if (f==0) throw Open_failure(n); } ~File_handle() { fclose(f); } // destructor // ... private: FILE* f; };
如果你未曾使用过类,你会觉得这番说明有些地方相当费解并且会低估类的用处。要寻找例子,请阅读一些经典书籍。
2、面向对象编程的伟大之处?
class Driver1 :public Driver{public:Driver1(Register);int read(char*, int);bool reset();Status check();};class Driver2 : public Driver { // 另一个驱动 public:Driver2(Register);int read(char*, int n);bool reset();Status check();// 实现细节 };注意,这些驱动含有数据成员,可以通过它们创建对象。它们实现了Driver中定义的接口。不难想象,可以通过这种方式使用某个驱动:
void f(Driver& d) // 使用驱动 { Status old_status = d.check(); // ... d.reset(); char buf[512]; int x = d.read(buf,512); // ... }
这里的重点是,f() 不需要知道它使用的是何种类型的驱动;它只需要知道有个Driver传递给了它;也就是说,有一个接口传递给了它。
void g() { Driver1 d1(Register(0xf00)); // create a Driver1 for device // with device register at address 0xf00 Driver2 d2(Register(0xa00)); // create a Driver2 for device // with device register at address 0xa00 // ... int dev; cin >> dev; if (dev==1) f(d1); // use d1 else f(d2); // use d2 // ... }注意,当 f()使用某个驱动时,与该驱动相对应的操作会在运行时被隐式选择。例如,当 f()得到d1 时,d.read() 使用的是 Driver1::read();而当 f() 得到 d2 时,d.read() 使用的则是 Driver2::read()。这被称为运行时调度或者动态调度。本例,f() 无法得知调用的是何种设备,因为那是根据输入选择的。
请注意,OOP 并非万能药。不要简单地把“OOP”等同于“好”。如果你的问题的基本要素中没有与生俱来的层级关系,那么类层级和虚函数对你的代码不会有任何帮助。OOP 的优势在于类层级可以有效地表达很多问题;OOP 的主要弱点在于太多人设法强行用层级模式解决问题。并非所有问题都应该面向对象。也可以考虑使用普通类(plain class)、泛型编程和独立的函数(就像数学、C,以及 Fortran 中那样)作为解决问题的方案。
3、为什么C++允许不安全的代码?
也就是说,为什么C++ 支持的一些操作能够违反静态(编译时)类型安全机制?- 为了直接访问硬件(例如,把整数当作指向设备寄存器的指针)
- 为了获取最佳的运行时效率和空间效率(例如,不检测访问数组元素的操作(是否越界)),不检测访问对象的指针(是否有效)
- 为了和 C 兼容(从此处跳到下一段落需要按两下enter)
- 不要用类型转换(cast)
- 不要将数组用作接口(如有必要,请将它们隐藏于高效函数和类的内部),而使用合适的string、vector等编写其余代码),
- 避免void* (如果你真的需要它们,请将它们限制于低级(low-level)函数和数据结构的内部,并且为用户提供类型安全的接口(通常是模板),
- 避免联合体
- 如果你对指针的有效性存在有任何的怀疑,请用智能指针,
- 不要“赤裸裸”地使用 new 和 delete (使用容器,资源句柄),
- 不要使用.....风格的函数(如printf)。
4、何谓泛型编程?其伟大之处何在?
泛型编程(Generic Programming, GP)是一种基于参数化(parameterization)的编程技巧:可以使用类型参数化另一种类型(例如,vector 的元素类型就是通过参数确定的);算法也可以参数化另一种算法(例如,使用比较函数参数化排序函数)。GP 的目的是将有用的算法或者数据结构尽可能地一般化,并使其最优化。例如,如果没有 GP,你必须为整型 vector 专门写一个类;然后,为了寻找其中的最大值,你又得为它写一个专门的函数。但是,使用 GP 可以把一切变得更美好:只需要写一个类,即可拥有任何类型的 vector;只需要写一个函数,即可寻找任何类型 vector 中的最大值。例如:
vector<string>::iterator p = find(vs.begin(), vs.end(), "Grail");
vector<int>::iterator q = find(vi.begin(), vi.end(), 42);
这些例子出自标准模板库(ISO C++ 标准库中容器和算法那部分)。TC++PL 中,漫游标准库那章对标准模板库(Standard Template Library, STL)作了简要的介绍。
GP 在某些方面比 OOP 要灵活得多。特别是,它不依赖于层级。例如,int 和 string 之间没有任何层级关系。总的来说,GP 的结构化程度更甚于 OOP。事实上,GP 常被称为“参数多态(parametric polymorphism)”;而 OOP 常被称为“ad hoc 多态”。就 C++ 而言,GP 于编译时就解析了所有名称;它不需要任何动态(运行时)调度。因此,GP 在对运行时效率要求很高的领域占据了主导地位。
请注意,GP 并非万灵丹。很多时候,程序并不需要参数化多态,而需要运行时调度(OOP)。
6、C 是 C++ 的子集吗?
- 一些无关紧要的好奇
- UniversalImageLoader源码解读03-一些无关紧要的小类
- 无关紧要的生活
- 无关紧要的句子
- 好奇号火星车的一些计算机软硬件信息
- C# (二)无关紧要的
- 批处理删除无关紧要的文件
- 写一点无关紧要的东西
- 新手的好奇
- 好奇!
- 好奇
- 编程语言的选择并非无关紧要
- 编程语言的选择并非无关紧要
- 下载Android源码时过滤掉无关紧要的大文件
- [wordpress技巧]优化wp_head 中无关紧要的代码
- 第一次开通,这是一篇无关紧要的文章!
- 令人害怕又好奇的熊
- 用户是好奇而脆弱的对象
- LM1875小功放电路解析与调校(出好声音)
- 10.css初始化
- [机器学习] SVM
- 关于web项目报"未明确定义列”的问题
- CF 423 C : String Reconstruction
- 一些无关紧要的好奇
- spark-submit提交任务到集群
- 学习日记-win7禁止软件安装
- Number String HDU
- 卓越的教练是如何训练高手的?
- MySQL5.7 linux二进制安装
- [Leetcode] 363. Max Sum of Rectangle No Larger Than K 解题报告
- 1043. 输出PATest(20) Hash散列
- android inflate初探