看C++Primer
1.在C++中,每个程序必须包含一个main()的入口函数,只有这样,这个项目才能运行.
2.函数包括:函数名,参数,代码,返回值.
3.return 是C++的预定义语句,提供了终止函数的一种方法;return 0表示成功执行正常退出.
4.using namespace std;是指引用C++的标准库.
5.
C++的4种基本数据类型:整数(int),浮点型(float),字符型(char),布尔型(boolean).
标准库扩展类型:字符型(string),复数(complex number),向量(vector)和列表(list);
vector <string> aa(20):表示定义了一个能放20个字符的向量对象:
vector <int> bb(20):表示定义了一个能放20个整数的向量对像.
6.
显示转换:将小转大,不会产生数据丢失.
隐式转换:强制将数据转换成另一种,可能产生数据丢失.大转小
7.
#include 的格式区别:
#include <some_file.h> 包含的文件是C++库中内置的类,或是标准的工程或头文件,查找方式是按操作系统的默认路径查找.
#include "my_file.h" 包含的是用户提供的头文件,查找方式按当前目录开始.
8.
#ifndef 表示检查是否定义某个变量,默认为假.
#define 表示定义变量
#endif 表示#ifndef的结束
9.
iostream C++的输入/输出流库.
包含以下内置对象:
cin:标准输入
cout:标准输出
cerr:标准错误
/n 表示换行
endl 表示换行
cout << "ddd"; 表示输出ddd三个字符.
cin >> names 表示读取用户输入的变量names
10.
连续出现的操作符可不用分号,以下正确:
cout << "dddd"
<< "1111"
<< "22222"
<<endl;
注意:每一个分开的值之前要加<<
11.
不能把一个数组单值赋给另一个变量.
int ddd=aaa[1]; //错误
也不能把一个数组赋给另一个数组
ddd[1]=arrry; //错误
12.
定义int类型的指针
int *pint;//声明了一个能存放pint的指针.
引用地类型是原变量的别名
ddd=&pint;//声明了别名
13.
静态与动态分配内存的区别:
1.静态对象是有名字的变量,我们直接对其进行操作.而动态对象是没有名字的变量,我们能过指针间接地对它进行操作.
2.静态对象的分配与释放由编译器自动处理;而动态对象的分配与释放,是由程序员显式(强硬)的管理,通过new与delete来操作.
14.
int *pint =new int(1024); //分配了一个没有名字的int类型对象,初始值为1024
int *pia =new int[4]; //分配了一个含用4个数据无素的数组.
delete pint; //删除单个对象
delete [] pia; //删除数组对象
15.
类修饰符
public 公共权限,任何程序都可调用
private 私用权限,只有本类或以下类可以调用.
protected 保护权限,只有本程序才可调用.
16.
作用域操作符::的作用:
(1)全局域和局部域都定义了相同名字的变量a,默认情况下局部变量隐藏全局变量,如果想调用全局变量a,应该这样:“::a”;
(2)调用类的静态成员:“类名::静态成员名”;
(3)子类中调用父类中被隐藏的成员:“父类名::成员名”;
17.
C++的关键特征是接口和实现的分离.
接口的概念:是一些"用户可以应用到类对象上的操作"的集合.
18.
构造函数与析构函数是相反的,一个是创造一个是销毁.
19.
面象对象软件设计的三个思想是 封装,继承,多态.
在继承类中,有相同代码的或先声明的叫基类,新类则叫派生类或子类.
20.
using namespace std; //引用C++标准库
也可用下面的代替:
std:stirng CurrenName="cowbo"; //引用std下的string库
或
using std::string;
21.
一个字节(byte)由8位构成,而一个字由32位构成.
22.
转义序列:
/n 换行
/t 水平制表键
/v 垂直制表键
/b 退格键
/r 回车键
/f 进纸
/a 响铃键
// 反斜杠键
/? 问号
/' 单引号
/" 双引号
*.可打印的文字常量可用单引号括起来
/14 表示换行
L'a' 表示宽字符
23.
int a=5;
a=a-1; //表示计算值必须要在右边,左边会被覆盖.
24.
多标识定义变量时,可以由逗号分开,并跨多行,最后以分号结束.
如:
int month,
day,year;
25.
C++初始化对象值的两种方式:
第一种:显式方法
int ival=1024;
string project="fantasia 2000";
第二种:隐式方法
int ival(1024);
string project("fantasia 2000")
26.
指针的定义是在前面加个*号,如:
string * cdd;//定义了一个cdd的指针.
string * cdd1,cdd2; //定义了一个cdd1的指针和一个普通字符串cdd2
cdd1=0; //表示指针没有指向任何地址;
当需要把指针指向一个地址时,要用
int a[10]; //定义了一个10位的数组
int *b=&a[10]; //定义了一个b的指针,指向a[10],一定要加&引用号.
27.
引用又称别名,通过前面加&号表示.
引用也要声明,例:
int Count=0;
int &RefCount=Count;
*如果在未声明的前提下,在已用变量前加&,则打印出来的是该变量指向的内存地址.
28.
C++可声明同名但不同类型的数据,但不能在同层内声明
29.
指针的概念
char *p;
p 是指针本身的地址
&p 指针所指向的值的地址
*p 指针所指向的地址的值
30.
在地址不确定的时候不能取地址中的值~~否则不安全
int* p;
int n=*p;//这是读
*p=n; //这是写
31.
在C++中,"="是赋值操作,而"=="是表示相等的意思.
32.
const定义的常量不可修改,但可以用其值来来计算.
int i=1;
const int ic=i;
cout << ic+1 << endl;
33.
int 的指针与int不是同一数据类型,例:
int i=15;
int *i=i; //这是错误的.
34.
在bool类型中,0为false,1为true
35.
C++的数组是从0开始的,
一个数组不能被另一个数组初始化,也不能被赋值给另外一个数组.而且不允许声明一个引用数组.
36.
两个整数相除的结果是整数,如果商含小数部份,则将被截掉.
37.
sizeof 是返回一个对象或类型的字节长度.
38.
指针可以让地址值增加或减少一个整数值.
39.
goto只能在函数体内跳转,不能跳到函数体外的函数
GOTO SUB;
.....
SUB:
40.
用个链子链起来的数据结构称为链表(链子一般为指针)
链表顾名思义,要把各个元素链接起来才算撒。
通常链表每一个元素都要保存一个指向下一个元素的指针(单链表)。
双链表的化每个元素即要保存到下一个元素的指针,还要保存一个上一个元素的指针。
循环链表则把最后一个元素中保存下一个元素指针指向第一个元素。
链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
41.
递增(++)
递减(--)
42.
strlen(char *str) : 求字符串长度
strcpy(char *dest, char *src) : 把src拷贝到dest
strcat(char *dest, char *src) : 把src连接到dest后面
strcmp(char *s1, char *s2) : 按照各个字符(ascii)比较s1和s2,相等则返回0,否则返回ascii相减的结果
strstr(char *s1, char *s2) : 在s1中查找s2,返回找到的位置,若找不到则返回NULL
43.
什么是堆和栈?
堆栈是一种执行“后进先出”算法的数据结构。
设想有一个直径不大、一端开口一端封闭的竹筒。有若干个写有编号的小球,小球的直径比竹筒的直径略小。现在把不同编号的小球放到竹筒里面,可以发现一种规律:先放进去的小球只能后拿出来,反之,后放进去的小球能够先拿出来。所以“先进后出”就是这种结构的特点。
堆栈就是这样一种数据结构。它是在内存中开辟一个存储区域,数据一个一个顺序地存入(也就是“压入——push”)这个区域之中。有一个地址指针总指向最后一个压入堆栈的数据所在的数据单元,存放这个地址指针的寄存器就叫做堆栈指示器。开始放入数据的单元叫做“栈底”。数据一个一个地存入,这个过程叫做“压
栈”。在压栈的过程中,每有一个数据压入堆栈,就放在和前一个单元相连的后面一个单元中,堆栈指示器中的地址自动加1。读取这些数据时,按照堆栈指示器中的地址读取数据,堆栈指示器中的地址数自动减 1。这个过程叫做“弹出pop”。如此就实现了后进先出的原则。
堆栈是计算机中最常用的一种数据结构,比如函数的调用在计算机中是用堆栈实现的。
堆栈可以用数组存储,也可以用以后会介绍的链表存储。
下面是一个堆栈的结构体定义,包括一个栈顶指针,一个数据项数组。栈顶指针最开始指向-1,然后存入数据时,栈顶指针加1,取出数据后,栈顶指针减1。
#define MAX_SIZE 100
typedef int DATA_TYPE;
struct stack
{
DATA_TYPE data[MAX_SIZE];
int top;
};
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多.
44.
::全局域,类域,名字空间.
.表示成员选择.
->表示成员选择.
[]表示下标.
new 分配对象.
.*,->*指向成员选择.
&&逻辑与
||逻辑非
?:条件表达式.
throw 抛出异常
45.
隐式转换:不改变值的转换.
显式转换:强制转换,可能会改变值.
int d=(int)3.1415926; //强制转换符放在前
46.
函数中,如果加入inline(内联)则表示,该函数在编译时就被调用;
如果没有加入,则表示函数在运行时才被调用.
47.
A.要在使用前先声明,否则函数将出错.
B.函数参数表不能省略,如果没有任何参数,可以留空或用void代替.如.int fork(void)
C.参数表中不能出现同名参数.
D.数组不能作为返回值.如int [] foobar(); //错误
E.C++中,数组不会按值传递,它只传递第一个元素(0)的指针.
如:
void a(int[10]);
被视为:void a(int *);
以下等价:
void a(int *);
void a(int []);
void a(int [10]);
F.当不确定有多少参数的数目时,用省略号(......)表示.
void foo(a,...)
48.
两个函数同名,但参数表不同,这种函数叫做重载函数(overloaded function).
49.
extern 的使用:
extern int m = 7; //这样写是定义m,compiler会为它分配空间。
extern int m; //而这样写是声明,compiler不分配空间。
50.
return 表示结束当前正在执行的函数,程序将把控制权交给此函数.
return 0 表示正常退出.
51.
直接或间接的调用自已的函数称为递归函数.
如.求最大公约数.
int GetMax(int v1,int v2)
{
if (V2!=0)
return GetMax(v2,v1%v2)
return v1;
}
//阶乘
unsigned long Fac(int val)
{
if (val>1)
return val*Fac(val-1);
return 1;
}
52.
1,extern可以置于变量声明前;
2,extern也可以置于函数声明前;
通过这种行为它告诉编译器:该变量/函数的定义已经存在在某个地方了,让编译器到其他的模块去寻找它的定义。
extern 的作用是告诉编译程式,后面所做的宣告只供型别检查使用,不需要将之实体化。
详细的说法是,相同的符号 (无论是变数或函数) 被宣告时,只要冠上 extern,编译器在遇到这些宣告时,只会检查所宣告的型别是否和曾经出现过的发生冲突,并不会配置记忆体空间给该变数,也不会设定函数或变数的 scope 范围 (所有 extern 符号 scope 都是全域,即使出现在函数内的宣告也一样)。
53.
extern "C" ;//告诉编译,该函数是用其它语言编写.
如:
extern "C" void Exit(int);
注意:extern不能出现在函数内.
extern int i;//表示告诉编译器,在其他的某个地方存在一下这样的定义int i;
54.
main()函数的作用:
1.后面的参数瑾于在执行EXE程序时用到.如:ping -t;
2.标准C++要用int main(){}
55.
C++有三种形式的域:
局部域: 包含在函数定义中的程序文本区.
名字空间域:
类域:
56.
全局函数/对象占据了存储区的生命期,从程序启动开始,在程序结束时结束.
全局函数:全局域内声明的函数.
全局对象:全局内的变量声明.
57.
头文件的作用:
1.保证所有的文件都包含同一个声明.
2.最少的改动.
59.
当需要一个类型的对象共享一个变量时会用到 static
定义静态函数的好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突
<2> 静态函数不能被其他文件所用。
类中的static成员:
一、出现原因及作用:
1、需要在一个类的各个对象间交互,即需要一个数据对象为整个类而非某个对象服务。
2、同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。
类的static成员满足了上述的要求,因为它具有如下特征:有独立的存储区,属于整个类。
二、注意:
1、对于静态的数据成员,连接器会保证它拥有一个单一的外部定义。静态数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。
2、类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致了它仅能访问类的静态数据和静态成员函数。
60.
new表达式的操作序列如下,从空闲存储区分配对象,然后用括号内的值初始化该对象.
例:int *pi=new int(0);
61.
delete表达式只能应用在:用new表达式产生的指针上,如上例.
62.
例如.需要的时候才分配一个字符串,但又不知道该字符串长度时才分配与释放的对象被称为动态分配对象.
动态分配的对象被分配在程序的空闲存储区的可用内存池中.
程序员用new来创建动态分配对象,用delete来结束时对象的生命周期.
63.
名字空间namespace表示方法:
namespace MySpace{
....
}
名字空间的别名:
namespace N=MySpace;
64.
什么时候用到extern
A,在此文件中声明别的文件的变量时用extern
B,在cpp程序文件中用到c的库函数时用extern
65.什么时候用到static?
A,声明静态变量时用static
B,声明全局变量时可用static
C,static型的变量是存储在静态存储的,他的值在程序运行时只初始化一次
66.
重载函数:
概念:允许多个函数共享同一个函数名,参数可不同但实现的功能相同,重载不关心函数的返回值类型.
目的:为多个不同参数不同名函数,但实现的功能相同的多函数,提供了一种简洁解决方法.
如以下均是重载函数:
① double calculate(double);
② double calculate(double,double);
③ double calculate(double, int);
① 和②可构成重载,②和③也可构成重载,① 和③也可构成重载.
成员函数被重载的特征有:
1) 相同的范围(在同一个类中);
2) 函数名字相同;
3) 参数不同;
4) virtual关键字可有可无。
67.
覆盖是指:
派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致
覆盖的特征有:
1) 不同的范围(分别位于派生类与基类);
2) 函数名字相同;
3) 参数相同;
4) 基类函数必须有virtual关键字。
68.
当一个函数在一个域(类)中被多次声明时,编译器会按如下步骤解释第二个(以及后续)的声明:
A.如果两个函数的参数表中参数的个数或类型不同,则认为这两个函数是重载.
void print(const string &);
void print(vector<int> &);//重载函数
B.如果两个函数的返回类型和参数表精确匹配,则第二个声明被视为重复,则产生编译错误.
void print(const string &str);
void print(const string &);//声明同一函数,错误!
C.如果两个函数的参数表相同,但是返回类型不同,则第二个声明被视为重复,则产生编译错误.
unsigned int max(int i1,int i2);
int max(int,int);//错误.
D.如果在两个函数的参数表中,只有缺省实参不同,则第二个声明被视为重复.
int max(int *ia,int sz);
int max(int *,int=10);
E.如果两个函数中,函数名和参数表都相同,而只是一个函数的参数表中有const时,则不能重载,因为const不可更改;但是当用在指针和引用上时例外.
int f(int);
int f(const int );//出错.
69.
注意:
重载函数必须在同一个类(域)中,不同类(域)间的函数不能重载.
70.
函数重载的解析过程:
当出现引用该重载函数时,检查当前类中,该同名函数的数量,然后分析那一个与当前最匹配,则选用最匹配做为解析,如转换出错,则返回错误.
71.
LPCSTR --- LPCTSTR ---- CString --- char* ----char[] ---- CHAR ---- 区别?
LPCTSTR 是将 const char* 类型重新定义
LPCSTR 是把 char*类型重新定义
CHAR 是把char类型重新定义
char[] 没有这个东西
CString是一个类,封装了常用的字符串操作
POSITION 是指集合中某个元素的位置.
如果要表示一个字符串可以这样
char str[32] = "a string";
char *buf = "bbbbb";
CString s = "ccccc";
如果要支持Unicode最好使用CString类,简单
72.
_T("")是一个宏,他的作用是让你的程序支持Unicode编码
如果你编译一个程序为ANSI方式,_T实际不起任何作用。
而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。
_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。
73.
1.快捷键
Shift+F4可查看上一个和下一个错误.
F5运行
F7编译
F9断点
F10步越调试
F11步入调试
SHIFT+F5结束调试
CTRL+F5运行
2.问题
改动源码后,F5时会弹出窗口提示.
变量生存期的问题:循环体内定义的变量在循环结束时就会被销毁,
指针就是地址,指针变量是用来存储地址的!当然,在定义的时候得定义好指针将要指向的变量是int, float ,char,double等中的那种类型。
基础问题:
1.作用域操作符'::'有什么用?
主要是用来调用全局变量,比如说在void main()的前面定义了int N;而在main中又定义了一个局部变量N,如果直接打印N,则显示的是main中的值;如果加上::,则显示在void main中定义的N的值.
(1)全局域和局部域都定义了相同名字的变量a,默认情况下局部变量隐藏全局变量,如果想调用全局变量a,应该这样:“::a”;
(2)调用类的静态成员:“类名::静态成员名”;
(3)子类中调用父类中被隐藏的成员:“父类名::成员名”;
2.可否给一个简单的指针代码?据说它能指哪就指哪?那它怎么指?
指针是可指向变量或是函数,和引用差不多,但机理不同.在定义了一个指针,比如:GetMax *M后,可以把其它变量的值赋给它,就是指向了.
int a = 1;
int *p = &a;
cout<<*p<<endl;
p++; //p指向非法区域
cout<<*p<<endl;
3.void main带参数与不参数的区别是什么?比如int main (int argc, char *argv[])?
main带参数可以从命令行给其传实参,不带参数就没有这样功能
4.为何控制台程序中,int main()中只能返回int,那如果要返回其它的类型要怎么改?
改成你要的返回类型就行了,但是好像没什么意义
5.return 0 是什么意思?那这个呢using namespace std ?;
return 0;向操作系统返回值表示程序正常退出。一般0表示正常退出,非0表示不正常退出
6.可否给一个简单的new和delete的代码?如何使用它们?
int *a = new int(1); // 分配一个整型空间初始化为1,将其地址赋给指针a
(*a)++;
delete a;
7.C++的重载函数怎么理解?
就是在继承中,重写父类的值.
重载是指不同的函数签名表示不同的函数,这里的签名是指“函数名+函数参数类型+参数个数”,不包括返回值。
请问int main()与void main()的区别 ?
声明函数的类型为整型,标准C++规定main函数必须声明为int型,因为它会return 0;
好好看书,另外以后提问要给分.
指针和引用的区别是什么?
引用只是别名,其地址与原数据一致,而指针是存放原数据地址.引用不分配内存,而指针分配内存.
指针是一种数据类型,其本身将占用内存空间它的值就是地址,引用不是值不占存储空间,引用只有声明没有定义,一但确定就不能改变,如:int a;int & i=a;i就是a的别名了,不能改变成别的变量的别名了;
指针则可以改变其值;如: int a;int;b;int *ps=&a;ps=&b; 按指针传递时虽然是直接对指针指向的值操作但是会产生指针本身的副本,所以有些地方要用到二级指针,而引用不会,引用是C++中的一个新的概念.
引用的一些规则如下:
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
什么样的类设计叫好类?
类的设计随着需求而变化,我们不可能拥有完美的类。各种性能几乎都是冲突的,取舍是关键。我个人认为类的设计有下面的要求:
1 能得到正确的结果,起码部分正确。
2 是健壮的,能够避免错误使用。能够监测异常(不一定是C++ 的exception),并且提交;或者能够屏蔽异常。
这往往与极端的执行效率相冲突,而它和强大的扩展性碰到一起则与往往与复杂性相冲突。
比如,当你不想提供copy ctor时,把copy constructor 声明为private之类就可以增加健壮性。 有时我们希望异常透明 —— 一旦发生意外就向上提交; 有时我们则希望屏蔽异常。比如,数组越界时,我们可以抛出异常,也可以返回一个哑元。 这取决于用户需要什么。
3 是灵活、低耦合、可重用、可扩展的。
这一旦和正确性、健壮性合到一起 —— 就成为巨大设计负担。
4 是高效的,时间上,空间上,资源利用上等等。
极端的高效,往往与上述2、3冲突,甚至与1冲突。 为了高效,我们有时候甚至不需要正确的结果 —— 只要结果“差不多”就可以了。
5 外部接口是简单清晰的,很好用。
这个有时候与上面2/3/4都冲突。 要安全,就往往带来麻烦,特别是C++异常。灵活也是一样。而为了达到高效,我们常常需要把东西复杂化精密化。
6 代码是简短的、清晰的、自解释的。
代码少而精简好处非常多 —— 他减少了bug的可能,他令阅读和维护都变得方便。但是他常常与1~5都冲突。
虚函数的作用是什么?
基本上是。如某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。当使用这个成员函数操作指针或引用所标识对象时,对该成员函数调用采取动态联编方式,即在运行时进行关联或束定
为实现多态作准备!!!
什么是虚函数???
虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。
什么是多态???
多态是面向对象程序设计和面向过程程序设计的主要区别之一,何谓多态?一名俗话说:“龙生九子,子子不同”多态就是同一个处理手段可以用来处理多种不同的情况。
析构函数和虚函数的用法和作用?
置于“~”是析构函数;析构函数因使用"~"符号(逻辑非运算符),表示它为腻构造函数,加上类名称来定义。
;析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。
有适放内存空间的做用!
虚函数是C++多态的一种表现
例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virturl(虚函数)。
使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。
如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virturl 函数名=0
我们把这样的函数(方法)称为纯虚函数。
如果一个类包含了纯虚函数,称此类为抽象类