[c++]c++程序设计-Y.Daniel.Liang 笔记

第九章:对象和类:
1.如果不适用public关键字,那么这些成员的可见性缺省为private。
2.自定义一个类时,应将类名中每个单词的首字母大写。
3.我们可能需要创建一个对象,却只使用一次。对于这种情况,无须为对象命名。这种对象称为匿名对象。(使用缺省构造函数)
4.包含保护。头文件中要有

#ifndef su_hpp
#define su_hpp

#endif /* su_hpp */

5.如果一个函数是在类定义内实现的,那么它就自动称为一个内联函数。这叫“内联定义”。也可以在实现文件中指明函数是内联函数。

第十章:面向对象思想:
1. string str(“this is string;”);
char a[20];
strcpy(a, str.c_str());
// c_str()返回的是一个临时指针,不能对其进行操作。string转换为c字符串
char* c;
string s=”1234”;
c = s.c_str(); //c最后指向的内容是垃圾,因为s对象被析构,其内容被处理

2.把数字转换为字符串

#include <sstream>
stringstream ss;
ss << a;
string s = ss.str();

C/C++语言提供了几个标准库函数,可以将字符串转换为任意类型(整型、长整型、浮点型等)。
参数都为char*

atof():将字符串转换为双精度浮点型值。
● atoi():将字符串转换为整型值。
● atol():将字符串转换为长整型值。
● strtod():将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字。
● strtol():将字符串转换为长整值,并报告不能被转换的所有剩余数字。
strtoul():将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字。

3.分割字符串

 string s("programming is so interesting.");
    stringstream ss(s);
    string word;
    while (!ss.eof()) {
        ss >> word;
        cout << word << endl;
    }
/*ss每>>一次就
会减少一些字符。
以空格作为分界线。*/

4.静态变量由类中所有对象共享。可以通过任何对象访问,也可以通过给定作用域访问。
静态函数不能访问类的实例成员(就是非static成员:数据成员和方法)。
静态变量和静态函数都无须创建对象就可以访问。

5.在函数前面定义const表明返回的内容为const!
在函数后面定义const表明不能改变数据成员!

6.面向过程的编程要点是设计函数,而面向对象范式把数据和函数结合在一起形成对象。使用面向对象范式进行软件设计的要点是对象及对象的操作。
7. 对象合成
一个对象可以包含另一个对象,两者的关系称为合成。
合成关系实际上是聚合关系的一种特殊情况。聚合关系建模了has-a关系,描述了两个对象间的所有关系。所有者对象称为聚合对象,其类称为聚合类。主体关系称为被聚合对象,其类称为被聚合类。
一个对象可以被多个其他聚合对象所拥有。如果一个对象被一个聚合对象所有,则两个对象之间的关系就称为合成关系。
简单地说,就是一个类里有另一个类的对象作为这个类的数据成员。
8. 类设计准则
第一:内聚
一个类描述的是一个单一的实体,该类的所有操作在逻辑上是结合在一起的,并且有一个连贯的目的。例如,学生和工作人员是不同的类。
有太多职责的实体应该分开成几个类,从而把职责分开。
第二:一致
遵循标准的编程风格和命名惯例,为类、数据域和函数选择有意义的名字。
遵循一致的命名原则。相同的操作,用重载。
第三:封装
如果希望数据域被读取和修改,应该给出相应的get、set函数。如果不希望被client访问则把这些函数设为private。
第四:清晰
类应该具有清楚的约定,既易于理解又易于解释。
用户可能以任意组合、顺序及在任意环境中使用类。在设计类时,不能引入任何限制,比如假定用户在什么时候如何使用类。在设计属性时,要注意,用户可能会按任意顺序和值来设置属性,在设计函数时,也应假定函数独立于它的出现属性怒。
如果一个数据成员可以被另一个数据成员导出,则类中不应该声明这个数据成员。
第五:完整
类可被不同的用户使用,为使该类更加有用,设计的类应该提供多样化得功能。
第六:实例和静态
因为构造函数总是用来创建特定对象,所以构造函数是实例函数。在实例函数中可以调用静态变量或静态函数,但是不能再静态函数中调用实例变量或实例函数。

第11章:指针和动态内存管理
1.

random_shuffle(<#_RandomAccessIterator __first#>, <#_RandomAccessIterator __last#>);
    min_element(<#_ForwardIterator __first#>, <#_ForwardIterator __last#>, <#_Compare __comp#>);
    max_element(<#_ForwardIterator __first#>, <#_ForwardIterator __last#>, <#_Compare __comp#>);
全都返回一个指针。
放入一个数组的指针和谓词。
  1. new操作符可以在运行时为基本数据类型,数组和对象分配持久的内存空间。
    c++中,局部变量在栈中分配空间,而由new操作符分配的内存空间则出自于自由存储区或者堆的内存空间。所以局部变量是非持久的,当函数返回时,调用栈中的局部变量会被丢弃掉。
    delete只能用于指向new操作符创建的内存的指针,不能用于delete基本变量。每个new操作都应有相应的delete操作。
    如果内存无法访问也无法释放,就称为内存泄露。

  2. 调用对象的构造函数可以动态地创建对象。
    new ClassName(arguments)

  3. 使用copy constructor将创建新对象,而是用赋值操作符并不创建新对象。
    缺省的拷贝构造函数和赋值操作符进行对象复制采用一种所谓的“shallow copy”,而不是”deep copy“,即如果数据域是一个指向其他对象的指针,那么简单复制指针保存的地址值,而不是复制指向的对象的内容。
    两个指针确实会指向相同的对象获得相同的内容,但是,当两个对象的析构函数释放内存时,就有会出现把指针重复删除两次,这会产生运行时错误。
    解决方法是,在复制构造函数中再声明一个内存,复制相同的内容。

第十二章:模板、向量和栈
当设计一个通用函数时,最好先设计一个非通用函数,调式测试完毕后,再将其转换为通用版本。
c++允许为模板类的参数类型指定一个默认类型。可以作为缺省类型。但是默认类型只能用于模板类,不能用于模板函数。
如果想要动态改变一个模板类的内存大小,可以预分配一个较小的内存,当这个空间满了,就另外分配一个更大的内存用于存储前面的内容,再把前面的内存释放掉。

srand(static_cast<unsigned>(time(NULL)));                                     int a = rand()%8 + 1;随机时间。实际上是根据当前时间来选择seed。

第十三章:文件输入和输出
ifstream用于从文件中读取数据;ofstream是向文件写数据;fstream既可以读也可以写。
ofstream output(“scores.txt”);如果文件已经存在,文件的内容会被清除,系统不会给出任何警告信息。
.fail()可以检测文件是否存在。
如果希望通过一个string名字作为文件名,需要把string类转换为char*。.c_str();
流控制符可用于格式化控制台以及文件输出。

setw(int)预定给出int个空格用于输出,如果字符量不够,则在前面加空格。
getline(<#basic_istream<_CharT, _Traits> &__is#>, <#basic_string<_CharT, _Traits, _Allocator> &__str#>, <#_CharT __dlm#>);

第一个参数是文件名,第二个参数是信息输入的变量,第三个参数是间隔符。
8.

char ch = input.get();(自动进入下一个字符)
output.put(ch);

第十五章:继承和多态
关于继承:
(1)基类的私有成员不能在该基类外访问,因此派生类中不能直接使用它们,只能通过特定的函数来访问。
(2)不是所有的is-a关系都要使用继承加以建模。
(3)继承用于建模is-a关系,但不要仅仅为了重用函数,就盲目拓展一个类。
2. 当程序需要一个基类对象时,向其提供一个派生类对象是允许的。这种特性使得一个函数可适用于较大范围的对象实参,变得更加通用。我们称之为泛型程序设计。
3. 构造函数链:构造一个派生类对象时,派生类的构造函数在执行自身任务之前会先调用其基类的构造函数。
析构函数链:与构造函数相反的顺序。
4. 如果考虑一个类可能被继承,最好为它设计一个无参的构造函数,以避免编程错误。
5. 如果基类有一个自定义的拷贝构造函数和赋值操作,应该在派生类中自定义这些来保证基类中的数据能被正确拷贝。
Parent::operator=(object);
6. 在基类中定义的函数能够在派生类中被重新定义。重新定义一个函数,则必须在派生类中定义一个与基类中函数具有相同签名和返回类型的函数。(在基类中定义为虚函数)
7. 多态意味着一个超类型的变量能够引用一个子类型的对象。
将一个派生类指针赋值成一个基类指针,称为向上转型,反之称为向下转型。(可以隐式进行)
8. 如果函数不会被重定义,将其声明为非虚函数会得到更好的性能。因为在运行时动态绑定虚函数会花费更多时间和系统资源。我们把含有虚函数的类型称为多态类型。

第十六章:异常处理
异常处理能够使程序处理一些特殊现象,并继续正确地执行。

try {
        throw <#expression#> // 抛出一个问题。
    } catch (<#catch parameter#>) { // 抓住这个错误。与throw同类型。
        <#statements#>
    }

异常处理使函数的调用者可以处理该函数引发的异常。

自定义异常类最好继承标准库中的基类。
多重异常处理。一个try模块可以对应多个catch用于捕获各种不同的错误。多个不同的异常类可以派生自同一个基类。如果catch模块被设计为接受一个基类的异常对象,那它就可以接受所有派生类的异常对象了。
多个不同类型的catch顺序是很重要的。基类的catch放在子类的catch后面。
还可以使用…作为catch的参数,用于捕获所有类型的异常。可以放在最后,用于捕获所有没有被捕获的异常对象。
一个异常通过一条函数调用链不断抛出,直到被捕获或到达main函数。
如果try模块内的一条语句抛出一个异常,try模块中剩余的语句将被跳过,c++启动搜寻处理异常的代码的过程。处理异常的代码称为异常处理程序。c++会从当前函数开始,沿函数调用链你想寻找异常处理程序。找到异常处理程序的过程称为捕获异常。
如果异常处理程序无法处理一个异常,或者它想通知调用者发生了一个异常,那么c++可以把它重新抛出给函数的调用者,使得其他异常处理程序有机会处理这个异常。
你可以在函数头部声明这个函数可能抛出的异常类型。 void check(double side) throw (NonPositiveException) 如果throw()放置于函数头之后,被称为空异常说明,表明函数不能抛出任何异常。如果函数试图抛出异常,c++会调用标准函数unexpected,终止程序。
抛出一个不在异常序列中的异常,也会终止程序。但是不带异常说明的函数可以抛出任何异常,而不会引起程序终止。
异常处理机制是针对以外情况的,不要用它来处理能用if语句解决的简单逻辑错误。
使用异常处理机制可以使程序更为健壮。异常处理可以将错误处理代码和正常程序分割开来,因此是程序更易读,易维护。

常用的流控制:

#include <iomanip>
    setprecision()设置精度
    fixed;显示小数点后面的数
    showpoint;显示小数点
    setw();设置打印字段
    left;
    right;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值