每日接触概念不清知识点2018.8.11
瀑布式开发和迭代式开发
瀑布式开发
瀑布模型式是最典型的预见性的方法,严格遵循预先计划的需求、分析、设计、编码、测试的步骤顺序进行。步骤成果作为衡量进度的方法,例如需求规格,设计文档,测试计划和代码审阅等等。
需求阶段通常定义系统的需求,明白系统的目标。
设计阶段通常确定系统使用什么数据库,系统模块的划分,各个模块的功能。
编码阶段用编程语言对设计阶段的实现。
测试阶段分黑盒测试,白盒测试。测试系统的功能是否实现,是否准确。
维护阶段是根据用户新的需要重新修改系统,使系统更加稳定,更符合用户的要求。
迭代式开发
每次只设计和实现这个产品的一部分,。
逐步逐步完成的方法叫迭代开发,。
每次设计和实现一个阶段叫做一个迭代.。
迭代式开发的优点:
1、降低风险
2、得到早期用户反馈
3、持续的测试和集成
4、使用变更
5、提高复用性
fseek函数
fseek
函数名: fseek
功 能: 重定位流上的文件指针
用 法: int fseek(FILE *stream, long offset, int fromwhere);
描 述: 函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字 节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
返回值: 成功,返回0,否则返回其他值。
int fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针
第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
简言之:
fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
fseek(fp,100L,2);把fp指针退回到离文件结尾100字节处。
运算符重载
类型类名::operate 重载的运算符(参数列表)
{
操作://……运算符处理程序代码
}
函数的参数个数是由以下两个因素决定:
该操作符是一元操作符还是二元操作符
当运算符重载为类的成员函数时,函数的参数个数比原有操作数个数要少一个(后置“++”,“--”除外),也就是说,一元操作符的参数个数为0,二元操作符的参数个数为1;而运算符重载为类的友元函数时,函数的参数个数与原有操作数个数相同(后置“++”,“--”除外),也就是说,一元操作符的参数个数为1,二元操作数的参数个数为2。这是因为,当重载为类的成员函数时,如果某个对象使用重载了成员函数,自身的数据可以直接访问,就不用再放在函数表中进行传递,这样该类本身也作为一个操作符参与了计算。
运算对象必须整型的运算符
~、^、&、|、%等都必须两边是整型
函数模板
所谓函数模板是由参数表示的一系列的函数。函数模板可以被不同的类型参数所调用,使用时和普通的函数功能一样,不同的是函数模板在定义的时候参数的类型是未知的。
例子
template <typename T>
inline T const& max (T const& a, T const& b)
{
// if a < b then use b else use a
return a<b?b:a;
}
#include <iostream>
#include <string>
#include "max.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
}
和普通的函数一样,函数模板也是可以重载的。
函数重载:不同的函数的定义可以有相同的函数名,当函数被调用的时候由编译器判断使用哪个函数。
非模板函数可以和同名的函数模板同时存在,也可以和相同类型的函数模板实例同时存在。当所有的条件都相同时,编译器会优先选择非模板函数。
1、函数模板可以针对不同的模板参数定义一系列的函数。
2、函数模板根据调用参数类型,实例化不同类型的函数。
3、调用时可以显示指定目标参数。
4、函数模板也可以重载。
5、函数模板重载是,不同的重载函数之间最好存在明显的差异。
6、必须保证所有函数都定义在被调用之前。
实例化
在面向对象的编程中,通常把用类创建对象的过程称为实例化,其格式如下:
如 Date date=new Date();就是用日期类创建了一个日期的对象,就叫对象的实例化。
多数语言中,实例化一个对象就是为对象开辟内存空间,或者是不用声明,直接使用new 构造函数名,建立一个临时对象。
抽象类不能实例化
保留字
并不是每一个合法的标识符都能被程序员所使用,有一些特殊的标识符,是不能用在用户自己的对象上的,他们被称作保留字。编译器需要使用这些保留字来分析程序的语法结构,进而理解程序。你可以把他们理解成英文里做助动词的have do 和助词that when why 的作用。程序中的 main int include return 都是保留字。都有对应的特殊含义。
虚函数、纯虚函数
继承有3种形式:私有继承、保护继承、公有继承,缺省的继承方式是私有继承。
不论哪种继承方式,派生类都是显示的继承类基的保护成员变量和函数和公有成员变量和函数,继承方式只是限定在派生类中这两种成员变量的访问方式(即访问权限)。私有的成员变量和函数也被继承到派生类中,但是不能被访问,它是隐藏的,在派生类中不可见。
派生类继承基类,除基类的构造函数和析构函数不外,其他的所有都继承。
派生类对象的构造/析构顺序
构造:构造基类成员对象–>构造基类–>构造派生类成员对象–>构造派生类
析构:析构派生类–>析构派生类的成员对象–>析构基类–>析构基类的成员对象
基类对象==>赋值给==>派生类对象 (X) 后面派生类的内存无法赋值
派生类对象==>赋值给==>基类对象 (V)将派生类中基类的部分赋值给基类对象
基类指针==>指向==>派生类对象 (V) 该指针智能访问从基类继承的那部分
派生类指针==>指向==>基类对象 (X) 可能非法访问内存
如果派生类继承了有被vritual关键字修饰的函数的基类,被vritual修饰的函数称为虚函数。派生类可以重写该虚函数。如果派生类重写了该虚函数,那么派生类对象调用该方法时调用的就是派生类自己实现的方法。如果派生类没有重写该方法,则调用基类的方法
纯虚函数是特殊的虚函数,基类中不能给出这个虚函数的实现方法,派生类必须给出该函数的实现。这种特殊的函数称为纯虚函数,有纯虚函数的类称为抽象类,抽象类不能实例化对象,但是可以定义抽象类的指针或引用,派生类必须重写方法后才能实例化对象。
C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。
C++的多态就是基于继承的,多态的实现就是调用虚函数时发生的同名覆盖。当用基类的指针(或引用)指向派生类的对象时,通过该指针(或引用)调用虚方法是动态联编的过程。先找到对象前4个字节的虚函数指针(vbptr),通过vbptr找到虚函数表,虚函数表里有函数的入口地址。
常见的面试题
<1>inline函数能否为虚函数? 不能!
<2>构造函数能否为虚函数? 不能!
<3>析构函数能否为虚函数? 可以!
<4>static函数能否为虚函数? 不能!
软件本质特征
复杂性
人们的复杂需求导致了软件的复杂性。当然导致软件的复杂性因素还有很多。
一致性
1.软件不能独立存在,要依附于一定的环境(如硬件、网络、以及其他软件)
2.软件必须遵循从人为的惯例并适应已有的技术和系统。
3.软件需要随从接口不同而变化,随着时间推移而变化,而这些变化是不同人设计的结果
**一致性大概可以理解为功能和其所依赖的环境、接口的一致。
可变性
软件的可变性体现在软件本身的升级,功能的变化等。
不可见性
1.软件是一种“看不见、摸不着”的逻辑实体、不具有空间的形体特征
2.开发人员可以直接看到程序源代码,但是源代码本身并不是软件本身
3.软件是以机器代码的形式运行,但是开发人员无法看到源代码是如何运行的