这几天C++语法考试,记录一下:html
a第一章:算法
1,面向对象程序设计的有点:数组
实现对现实世界客体的天然描述。app
可控制程序的复杂度。ide
可加强程序的模块性。函数
可提升程序的重用性。this
可改善程序的可维护性。spa
第二章:设计
1,cin -> stdin; cout -> stdout; cerr->stderr;clog->stdprn,cerr和cout的区别就是他不可以被重定向。指针
2, 命名空间的声明 namespace mfc {int inflag;} 同一个命名空间能够定义屡次。
using 用多了会冲突。
3,cin>>x>>n,这个输入到x,n主要是经过空格来隔开的。也是经过空格表示结束。
4,dec 十进制, oct八进制,hex十六进制,cout<<hex<<i<<endl;一旦进入这个状态就不能改变了。例如,cout<<hex<<i<<endl; cout<<i<<endl; 两个都是十六进制。
5,setw若是不够大小的话不起做用,若是比原来的大的话从左边填充。setw是一次性的,就是说若是输出了,就不会见效了,必须从新来。例如,cout<<setw(3)<<3456,这个不会扩大,而cout<<setw(7)<<3456就会左边填充空格,以后cout<<3456又回到wide = 0的默认值了。这个东西是iomanip文件中的,须要include <iomanip>
6,setprecision()这个在double地时候是表示留下几位。例如,33.33 setprecision(2), 33.3,若是有fixed,就是小数点固定,就表示小数点后面几位的。例如,33.3333 fixed + setprecision(2) 为33.33 表示小数点以后的留下几位。
7,ifstream fstr(path) ofstream istr(path)
8,const int* a 这个表示所指向的内容不会变。int* const a 表示指针a不能变。
9,float j = static_cast<float>(i). const_cast<int> 把const转化成为不一样的。
if(typeid(*base) == typeid(Derived1)) {
Derived1 *derived1 = static_cast<Derived1*>(base);
derived1->showOne();
}
static_cast和dynamic_cast就是都是经过是基类转化成为派生类。可是static就是强转化,而dynamic_cast是弱转换。若是失败会跑出bad_cast的异常。
若是device& x, dynamic_cast<deviceBase&>(x)....须要注意引用的应用。这里面须要注意的是dynamic_cast<D> D 必定是引用和指针。
reinterpret_cast用于不一样类型的转换。
10,bool的地方也能够用Int是否等于0来判断。-1也是true。
11,string是以NULL为结尾的。string s4(10,'X'); string s3 = s2; int 转化成为string 用<sstream>中的stringStream,由于是流.例如:
string str;
stringStream strStream;
int i = -1;
strStream<<-1<<endl;
strStream>>str;
cout<<str<<endl;
12,遍历文件夹getline
#include <string>
#include <file>
using namespace std;
int main(char* args[])
{
string str;
ifstream input("C:\\source.txt");
ofstream output("C:\\dest.txt");
while(getline(input,str))
{
output<<str;
}
input.close();
output.close();
}
这里须要注意,file的空间和getline的返回。
13,erase(开始位置,长度);insert(插入位置,插入的字符串);replace(替代位置,子窜大小。子串。),swap(字串),find("",startPos), 字符串支持 == > < != 这样的操做。
14,int main(int argc,char * argc[]){...}
15, 引用,通常都是用于参数传递的时候用,这样可以对这个参数进行修改。不能然会局部变量的引用。
16,inline函数的限制:
a,不能包括复杂的结构控制语句(while, switch)。
b,不能包括内联函数自己。
c,不能是直接递归。(本身内部还调用本身的函数)
17,inline和宏的区别:
a,宏是预处理器进行替代,而inline是编译实现的。inline有更强的约束性。
b,inline函数是真正的函数,是准寻函数类型和做用与规则。
注意:类中的inline函数通常都是在.h文件中直接定义。
18,函数签名不包括返回值,因此不能只看返回值。
19,函数的默认参数必须从右边开始。
20,
第三章:
1,C++中class 的默认的做用域和private是同样的。而struct的默认的是public同样的。
2,inline在类里面,若是在.h生成的就是内联函数。若是是分开定义的,那么就在.h定义这里面加上inline字符就能够了(注意cpp不要加。)
3,
成员函数+const 就是让属性值不要减小。 例如:GetValue() const{return this->a;} 这里a不能有。
并且这里面不可以调用non_const的成员函数。
4,若是函数返回类型采用const的话,那么,只能赋值给一个const类型的局部变量。
5,
对象数组,当调用对象数组的时候,会默认调用每一个对象的构造函数。C ar[1000] 会调用1000次构造函数。若是没有够着函数,会默认生成一个默认的。
若是有了一个公有的,就不会生成默认的。
默认的够着函数,里面的类成员不能被初始化。
6,
拷贝构造函数:Person(Person& person)和Person(const Person& person),拷贝构造函数能够有多个参数,可是这些参数必须有默认值。
当函数中有一个属性指向了动态存储空间的时候,应该调用拷贝构造函数。默认的只是直接赋值,这样,两个对象的指针就指向同一个对象了。若是命名了拷贝构造函数的话,就不会有默认的了。
这个时候,若是把这个拷贝构造函数放在私有,这样就禁止了拷贝构造函数。
7,转型构造函数,里面要用到一个explicit。但是实现隐形转换。
8,初始化够着函数列表。Person():x(1),y(0),并且const只能经过这来初始化。
9,类静态成员的声明,int C::s = 0;并且若是没有用static标明,不可以在函数中声明。
10,const 对象不可以调用成员函数,主要是由于这样可以改变这个类里面的值。
第四章:
1,C++ 支持多重继承,就是一个类能够同时继承多个类。
2,经过using能够在子进程中改变基类的控制范围。例如:
class BaseClass
{
public:
BaseClass(int value);
int GetValue();
void SetValue(int i );
private:
int value;
}
class derivedClass: public baseClass
{
public:
DerivedClass(int a ,int b):BaseClass(a),valueB(b);
void SetValue(int i);
private:
using baseClass::GetValue;
int valueB;
}
3,若是继承以后新成员(成员函数,成员变量)名称(只同名就能够)和基类的同名,他将会覆盖这个老成员函数。其实也无所谓隐藏,BaseClass::SetValue()和DerivedClass::SetValue()来区别的就好了。
4,在公有继承的方式下,保护成员是可以被子类看到的。
5,构造函数和析构函数是不可以被继承的。当派生类没有本身的构造函数的时候,会直接调用父类的默认构造函数。若是没有声明,在调用本身的初始化构造函数的时候,调用父类的初始化构造函数。
例如上面的类:若是子类没有构造函数而父类有,这样的话,父类的构造函数必须有默认构造函数。其实就是说,若是要是显示调用了基类的构造函数的话,就不须要了。若是要是没有显示,须要父类有一个默认构造函数,子类会调用。
6,析构函数的工做和构造函数的调用顺序正好相反。并且,析构函数每一个类至多只有一个。
7,类成员初始化的顺序取决于他在被继承时所说明的顺序,并不是初始化队列的顺序。
8,多重继承的时候,若是两个基类有同名的函数,这样的话就会发成冲突会出错。
多继承的构造函数顺序,基类的构造函数先被调用,数据成员所在类的构造函数次之,最后指向派生类的构造函数。这个其实就是由于构造函数的时候先执行父类的,而后才是属性复制,而后才是当前的构造函数。
9,虚基类,当多重继承的时候。例如:
class C : D1,D2
{
}
class D1: B
{
}
class D2: B
{
}
class B
{
public: int x;
}
这个时候当生成C的时候,会生成两个B class的副本(内存里面是两个B的对象),这个时候,若是 C.B::x = 2; 是有问题的,由于这个时候并未指明是哪一个B 的副本。并且,当你调用C.x的时候也有二意性。C.D1::x 和 C.D2::x不是一个值。可是,若是上面的全都是弄成虚基类。也就是以下:
class D1 : virtual B
class D2: virtual B
这个时候就只有一个副本了,C.B::x =2 只有一份,不会有歧义。C.x也是。还有虚基类的构造函数最早调用。
10,继承分为三种继承:
公共继承,公有的-》公有,私有的—》不可访问,保护的-》保护
私有继承,公有的-》私有,私有的—》不可访问,保护的-》私有
保护继承,公有的-》保护,私有的—》不可访问,保护的-》保护
11,类型适应:派生类的对象,引用,指针均可以赋值给基类的。
第五章:
1,虚函数这个东西,须要在基类上面定义virual函数,子类若是不定义也能够(不定义回去找同名的),定义更好。虚函数的主要目的在于动态绑定,若是不是虚函数,那就是对象是什么就调用什么,而若是是虚函数,就是调用真正的。若是在外面定义的函数,只须要在生命时候加上virtual就能够了。
例如: Base a; Derive b;
a = b;
a.print(); 若是print是虚函数,调用的就是b.print,若是不是调用的是a.print。
如今有这么一个例子:
Class Base{
void Act1(){Act2();}
void Act2(){cout<<"ori act2"<<endl;}
}
class Derive:public Base
{
void Act2(){cout<<"dest act2"<<endl;}
}
Derive b; b.Act1(); 输出是?
ori act2
若是把Act2 变成虚函数,这个时候结果就是 dest act
这里主要是由于这个时候this指针已经多态了,你能够把this当作 Ori* source = new Derive();
2,析构函数能够是virual的。只要加了virtual,派生类的就都不须要加了。vitual析构函数的做用是delete 子类的时候(可是这时候是动态绑定,内容是子类的,表表面是基类的),会调用子类的析构函数,以后还会调用父类的析构函数。若是要是没有virtual,动态绑定的时候,对不会调用子类的析构函数。若是是其余函数,若是派生来加上了virual就是说它如今也是虚函数,下面的人能够覆盖。
3,静态成员函数不能够是虚函数。
4,重载:就是同一个类,两个不一样样签名的函数。---》编译绑定
覆盖:基类子类,虚函数,两个一样签名(不含返回值)的函数。---》动态绑定
隐藏:基类子类,不是虚函数,函数名字相同就行。 ---》编译绑定
若是虚函数,若是不产生覆盖(在只有函数名字相同的时候),就会产生隐藏。
5,纯虚函数主要是的写法是: virtual void open() = 0; 又纯虚函数的类不可以产生对象。
6,在#include <typeInfo> 中typeId()
也就是typeid(对象,引用,指针) == typeid(类,引用,指针) 例如class A;... A a; if(typeid(a) = typeid(A)){cout<<"TRUE"<<endl;}
7,动态函数中调用虚函数,搜现实调用本身类实现的,若是本身类没有实现,就调用基类的虚函数。不会调用其余派生类的。
第六章
1,不能被重载的运算符:?: . * ::;除了=以外,其余的均可以被派生类继承。操做符重载不改变优先级和集合率。
2, 顶层操做符重载在定义的时候必须就不是相类成员同样了。他就没有默认的类对象当作参数。并且必须明确的指出来。
例如,C operator+(const C&c, const C& c2) 这个主要就是 Cresult = c + c2;
而且,对于顶部操做符重载,咱们须要用到一个自定义个类。若是要是没有的话,区分不了。
这样的操做都是顺序的,例如:C operator[](Point& s , int i)就是 s[i]这个样的一个东西。是有前后顺序的。
对于二次型操做符,与使用类成员函数相比,只要定义了可转型的构造函数,使用顶层函数进行重载是能够不用在意左右两边的。若是用类的话,第一个参数必须是类对象。(恶心:()
3,友元函数其实很简单,就是在一个类里面的方法的前面加上friend,放在public,protect,private均可以,反正不是这个类的函数。这样在外面定义的时候不须要加上friend,这个时候这个函数就可以访问这个类的私有和protect的变量的。例如:
class A
{
public:
void Print();
friend void PrintOut();
friend B::PrintA();
friend C;
private:
int a;
}
class B
{
public:
void PrintA();
}
class C
{
public:
void PrintA()
{
cout<<a<<endl;
}
}
void B::PrintA()
{
cout<<a<<endl;
}
void PrintOut()
{
cout<<a<<endl;
}
如上面,友元能够为一个类,一个类的成员函数,一个顶层函数。可是,咱们只建议在顶层操做符的时候使用。
3,>>的操做符重载,这里通常第一个参数通常都是istream的引用。返回的也是。
()函数操做符的重载,double operator()(double x,double y) const { return x*2 + y;} ,这个就是f(1.5,3.2);
counter operator ++(); 前缀操做符 counter operator++ (int); 后缀操做符,后面的int就是为了代表是后缀操做符。
第七章
1,模板这东西实际上是编译程序会根据函数调用的实际状况把T所表明的类加载进去。因此,若是T出了问题编译是不能经过的。
函数模板在应用的时候,不要用<>来制定类型,他会直接经过传入的参数类型直接定义T的类型。例如:
template<class T>
T Sum(T a,T b)
{
return a + b;
}
void main()
{
int sum = Sum(1,3);
}
2, 模板这个东西的格式比较好玩,就是生命的时候呢,类用永远和《T》不要紧,可是在定义的时候<T>必定要制定了。并且,在它用于当作做用域的时候也须要制定。这个函数就不是了,模板函数不须要指定。例如,
template<class T, int i>
class A
{
public:
T a;
T Get_a_Value();
}
template<class T,int i>
T A<T,int i>::Get_a_Value()
{}
void main()
{
A<int,5> a;
int i = a.a;
}
并且还有一点须要注意,就是当你声明template的类时候,这个类的方法好像必须定义在.h文件当中。
3,这里还有一个值得注意到地方,不一样T的template类是彻底不一样的两个类,例如上面的A<int,3>和A<int 4>;A<double,1>和A<int,1>;不是一个类型,因此他们不可能拥有同一个基类,同一个静态变量。而A<int,4>和A<int,4>的对象就是同样的。
4,STL包括容器,算法,迭代器,函数对象,适配器,配置器。
5,迭代器就是一个封装了的指针,指向一个容器的每一个数值。他重载了*符号,访问他说指向的值。还有他重载了++运算法。能够移动。
有向前迭代器和向后迭代器,向前就是++向前,而向后就是++向后移动。还有,他有const不const,若是是const代表不可以改变iterator的值。
6,list -> 双向链表
vector -> 能够伸缩的数组
deque -> 两端进行有效插入删除的数组。
set 不含重复值的集合
map 键值不能够重复
multiset 容许重复值的set
multimap 容许重复键值的map
vector 适合在尾部插入删除的操做,deque适合两边插入删除的操做。
list不可以经过下标访问。
7,stack,queue, priority_queue: stack,queue默认派省委deque;priority_queue默认为vector
stack<char> s;默认 stack<char,vector<char>> s
8,bitset记录二进制,bitset<8> bs --8位0 bitset<8> bs(9) --8位表示9
其余积累:
1,C++中没有finally,必须用try catch来搞定,或者用对象控制。
2,C++中最好不要用两层的调用。例如:a.b.c.size();
3,类的参数初始化在.h文件中就行。
4,typeid 是<typeinfo> 命名空间的。 dynamic<t>这个T为目的端的。typeid只对有virtual的虚类才有做用。也就是 polymorphic class type。http://www.cplusplus.com/reference/std/typeinfo/type_info/
5,vector 中的=就是copy。
6, 在C++的.h引用中,用#ifndef classFlag; #define classFlag #endif的方法,这个防止类重复定义。
7,一个类的私有函数其实就是一个类的private,是针对于类而言的,并非针对于对象而言的。例如,拷贝构造函数中就能够在当前的构造函数中,调用另外一个同一个类对象的私有成员变量。例如:
A(const A& a)
{
this.num = a.num; //num是A类的私有成员
}
8,函数中char * a = "helloworld" 这个字符串是放在堆里面的。char a[] = "helloworld"是放在栈里面的。
9,explict 是用来避免隐式转换的。不少时候构造函数肯能会有隐式转换功能。例如:
A(int a);
A a(0); a = 5; 其实就是 A temp(5); a = temp; ~temp();
若是不想隐式转换,就必须用explicit。上面为explicit A(int a)就能够了。
http://wenku.baidu.com/view/2d94f7264b35eefdc8d3334d.html
10,extern 的做用:他能够用于修饰变量和方法,它的主要做用是防止在一个.h文件中定义的一个对象,而在另外一个文件中须要用extern链接。若是没有extern这个时候编译会出错误。由于他们都是先编译以后链接,若是编译以后再链接,就会出现同名的错误。
例如:a.h: int a; b.h extern int a 这个时能够的,方法也是,可是若是要是没有extern 链接的时候就会冲突
extern 'C' 这个主要做用就是为了让C++引用C中的方法的变量,由于C++ 有的时候编译的C是不同的。例如,C++有函数重载的概念,而C老是没有的。因此int find(int a,int b)在C++ 编译以后会是 _find_int_int(注意没有考虑返回值),而C中的只有_find。这个时候若是不用extern,就会出现找不到函数的现象。
因此,须要在引用.h文件时候。extern 'C'{#include 'ac.h'},或者单独定义函数。
10,函数指针int* (*function)(int a, int b).
11, int const* p 和const int* p是同样的都是指向一个指向一个const int的指针,而int * const p才是指针不会变化的那种。 const int* const p呢 ?
12,UTF-8 3bytes UTF-16 2bytes。
13,__thiscall __cdecl这两个主要是标明当前这两个方法的主要类型,thiscall是类的成员函数,他在应用函数指针会出现问题,由于thiscall的函数基本都是经过类以后找函数表实现的,它的内部机制和普通的函数指针有所不一样。而cdecl是回调函数,这个有一点好处就是函数指针能够直接引用。通常外围函数,和类的静态函数是cdecl的。这里须要注意若是你须要应用thiscall,就须要用到mem_fun和mem_fun_ref这两个STL类,他们的主要做用就是转化的。详细请看http://apps.hi.baidu.com/share/detail/4994454
14,C++存储区中分为堆,栈,静态存储区。通常常量是放在静态存储区里面的。
15,动态连接库是在进程启动的时候加载的。
16,只有指针才能动态绑定,对象是不行的。