- static类数据成员是与类关联的,但不与该类定义的对象有任何关系。static类对象必须要在类外进行初始化。所有对象共享一个static类成员。即声明在类内加static,定义在类外。
- 类的成员函数也是属于类本身,而非对象的。只在头文件声明处加static,源文件定义不需要static.静态成员函数不可以调用类的非静态成员。
- 在类外的回调函数调用类的成员函数,要头文件类的成员函数声明处加上static,变成静态函数。表示该函数属于类调用,而不是类对象调用。因此在回调函数中调用class::Function 的形式。即静态成员函数作为回调函数参数。
- 在一个程序中只能对变量定义一次(源文件),而可以对变量进行很多次的声明(头文件)。如全局变量,在头文件声明 extern int g_nIndex ; 源文件 定义int g_nIndex = 0;
- 数组指针 int *a = new int[10]; delete []a;
- 指针数组 int *a[2]; for(int i = 0; i<2;i++){ a[i] = new int[10]; } for(int i = 0; i<2;i++){ delete []a[i];}
-
io 流操作 1. iostream类: 负责与控制台输入输出打交道, 这个我们已经很熟悉了。 注意: 实际具体又可以区分为:istream和ostream 2. fstream类: 负责与文件输入输出打交道, 这个我们接触过。 注意: 实际具体又可以区分为:ifstream和ofstream 有get、getline、write、cin、,<<等操作。
-
#ifndef 宏 #define 宏 endif 和#pragma once 两者都是为了避免同一文件被include多次
-
stdafx.h 的作用 ;由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。1.AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要MFCinclude 文件。2.AppWizard然后就建立stdafx.cpp。3.这样第一个被编译的文件就是stdafx.cpp,它将结果保存在一个名为stdafx.pch的文件里
4.当VisualC++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。VisualC++不再分析Windowsinclude文件 所以:1.你编写的任何.cpp文件都必须首先包含stdafx.h。2如果你有工程文件里的大多数.cpp文件需要.h文件,顺便将它们加在stdafx.h(后部)上,然后预编译stdafx.cpp。
-
从stl引申到mfc相关的模板,如carray 、clist、Map到 ctypedptrarray 、 ctypedptrlist、ctypedptrmap.
CArray<Object,Object> Var1; //Object表示某种数据类型或结构
CArray<Object,Object&> Var2; //更高效 CArray添加元素可能导致数组经常重新分配和复制,这样做效率很低而且可能产生内存碎片。查找检索快、添加删除慢。CList<Object,Object> Var1; //Object表示某种数据类型或结构 CList<Object,Object&> Var2; //更高效 Clist 是查找慢,添加删除快。 CTypedPtrArray<CPtrArray,Object*> Var1 CArray是保存对象的数组,CTypedPtrArray是保存对象指针的数组 CTypedPtrList<CPtrList,Object*> Var1 CList是保存对象的数组,CTypedPtrList是保存对象指针的数组 对于保存对象指针的数组,如果是通过new方式创建数据,需要使用delete释放。
-
标准的stl 的vector 和 list
Vector:顺序表,连续的内存空间,支持随机访问,查找效率高其时间复杂度O(1)。插入删除会需要对数据进行移动比较麻烦,时间复杂度O(n)。所以适合于对象数量变化少,随机访问元素频繁.函数有push_back、insert、pop_back、clear等 List:链表,循环双链表,不连续的内存空间,数据存储在堆上,当对大量数据进行插入删除时,其时间复杂度O(1) 。只能通过指针来访问,所以查找数据需要遍历其时间复杂度O(n)。适用于对象数量变化大,插入删除频繁。 - 尽量使用vector代替C风格的数组或者CArray。因为插入效率高多了。
- stl 的算法,最常用的就是排序,std::stable_sort();如std::stable_sort(vector.begin(),vector.end(),静态函数指针);再引申到qsort()函数。
- 构造函数和析构函数。可以有多个构造函数,可有参数,无返回值。析构函数只有一个,且是虚函数,无参数,无返回值。
- 友元函数:不是类的成员函数,而是独立于当前类的外部函数,但他可以访问该类的所有成员变量(包括私有成员)。声明友元函数需要在函数前加friend。一个类的成员函数也可以作为另一个类的友元,一个类也可以作为另一个类的友元。
- mfc的基类:cobject类
- c++ 类型转换运算符 有4种:static_cast、dynamic_cast、reinterpret_cast、const_cast。其中:dynamic_cast 特别适用于多态情况下,把基类的指针转换到子类的指针。
- 智能指针 auto_ptr
- 防范多重包含 2种方式 #ifndef AAAA #define AAAA #endif 和 #pragma once 这些操作都是在预处理时执行的.
- assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行。在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用.
#define NDEBUG #include <assert.h>
- const 成员函数,如 viod func () const; 必须保证该方法不会修改任何类的成员的值。
- 内联实现:inline适用的函数有两种,一种是在类内定义的成员函数(可以不用在函数头部加inline关键字,因为编译器会自动将类内定义的函数声明为内联函数);另一种是在类内声明,类外定义的成员函数(在类内声明时不加inline关键字,而在类外定义函数时加上inline关键字)。在内联函数内不允许用循环语句和开关语句,内联函数只适合于只有1~5行的小函数。
-
构造函数为什么不能使虚函数
1.虚函数对应一个虚指针,虚指针其实是存储在对象的内存空间的。如果构造函数是虚的,就需要通过 虚指针执行那个虚函数表(编译期间生成属于类)来调用,可是对象还没有实例化,也就是内存空间还没有,就没有虚指针,所以构造函数不能是虚函数。2.虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。
-
C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式). explicit关键字的作用就是防止类构造函数的隐式自动转换.explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了.
-
封装:如果某些东西被封装,它就不再可见。愈多东西被封装,愈少人可以看见它。而愈少人看到,就有愈大的弹性去改变它。
- 当用一个对象去初始化同类的另一个对象时,会引发默认复制构造函数被调用 如 Complex c2(c1); 和 Complex c2 = c1;
-
volatile是一个特征修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
-
参数传递顺序有从左到右传递、从右到左传递两种,由于参数也是一个表达式,关注参数的求值顺序对写出正确的程序非常关键。具体见:https://blog.csdn.net/baidu_16370559/article/details/121158869
-
编译器释放对象的过程分两步:调用其析构函数释放持有的资源,然后释放对象占用的内存
string * pNameArray = new string[3];
delete pNameArray; // 内存泄漏
//由于它使用普通对象释放操作,第二个、第三个字符串对象未调用其析构函数,字符串对象持有的资源未释放,导致内存泄漏
应该是 delete [] pNameArray;