C++两本巨著primer plus和primer太过于经典,以至于读过多次,每次阅读仍然有新的收获,所以将一些零碎的知识点整理在这里,与大家共同进步。
1.i++与++i的效率比较:
前缀效率高,后缀在递增前需要一个副本。
2.typedef和define的区别
define进行简单的替换,但是typydef可能带有类型。
#define float_32 float*
typedef float* float_32_1;
float_32 ptr1, ptr2;
float_32_1 ptr3, ptr4;ptr2是float,其他是是指针。
3.关于char类型
char类型有没有符号取决于实现。
char ch;
while(ch = cin.get()!=-1)//可能存在的问题,char为unsigned
{cout<< ch;}
4.关于&&和||优先级的问题
&&优先于||
int y=1,x=2;
int z=y||x++&&++x;
cout<<x<<y<<endl;
最后输出的y=1,x=2.因为||截断。优先级只能保证结合的方式,int z=y||(x++&&++x),但是不能保证执行的顺序。
5.二维数组传参的方式
int data[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int sum(int (*data)[4] , int n){
}//或者 int sum(int[][4],3){}
6.泛型中函数匹配,最佳到最差:
(1) 完全匹配//非const优先非const,在指针和引用的情况下
(2)最佳转化
(3)提升转换
(4)用户定义转换
7.作用域与链接性
static的两种用法:
(1)局部变量中表示变量是无链接性的静态变量,表示的是存储性。
(2)外部声名表示内部链接性。
全局变量的const=static const,如果想让const变成外部链接性则:extern const
8.使用using实现静态变量封装
匿名namespace。namespace{a;b;c};相当于static修饰。
9.类中的常量
class Barkery{
const int month = 12;//C++11可以,但是不可以将其用作数组
double array[month];//报错
};
//可以使用的两种方法
(1)
class Barkery{
enum{month=12};
double array[month];
};
(2)
(1)
class Barkery{
static const int month=12;//将month和其他的静态变量放置在一起。所有的类共享一个month
double array[month];
};
类中的静态变量
class Barkery{
static int month;//将month和其他的静态变量放置在一起。所有的类共享一个month
};
int Barkery::month = 12;//不能在类中初始化,类外初始化不需要static修饰。
//
//
//类中非静态const成员的初始化方法
class MyClass
{
const int size;public:
MyClass(int s) :size(s) {}
void show() {
std::cout << size;
}
};//const变量只能列表初始化//对于引用的成员,也只能使用成员列表初始化的方式进行初始化
//这是因为对于常量和引用,必须在对象创造的时候进行初始化。
10.作用域内枚举
int main() {
enum zyh {big,small};
enum zxf {big,small};
zyh a = small;
zxf b = small;
return 0;
}//报错,因为两个枚举类型元素相同,重复定义int main() {
enum class zyh {big,small};
enum class zxf {big,small};
zyh a = zyh::small;
zxf b = zxf::small;
return 0;
}//修改为作用域内枚举
11.友元
友元函数
友元类
友元成员函数
友元函数,类中声名友元函数,可以像成员函数一样的调用私有变量。
定义的时候不需要类名限定符。定义中不需要friend
友元类
12.关闭隐式构造
class Stock{
float a;
public:
Stock(float price){price = a};
};
Stock sda = 3.2;
有的类的构造函数只有一个参数。存在上述隐式转换。可以在构造函数之前加上explicit取消这种存在风险的转换。
13.类型转换函数
将类类型转换成常规类型:
operator double()函数。
要求三点:1.必须是类方法
2.不能带有参数
3.不能指定返回类型
同样可以采用explicit防止隐式的转换。
14.静态成员函数
静态成员函数只能访问静态的变量,且不能使用对象 调用。
15.类的构造函数中的成员列表初始化
(1)初始化const
(2)初始化引用
(3)初始化基类的构造函数
16.虚析构
通常需要将基类的析构函数设置成为虚函数,为了正确的调用继承链上的析构函数。
17.子类重新定义基类函数
重新定义基类函数,并不是重载,而是隐层了基类的方法,而不管特征标的形式。
在派生类中应该定义所有的基类版本。
18.含有new的派生类中,赋值函数如何对基类部分进行赋值
调用基类的赋值函数:baseClass::operator=(hasClass);
不能使用 *this=hasClass//会导致赋值函数的递归调用
19.定位new到的对象如何delete
显示的调用析构函数
20.私有继承和组合实现has-a的关系
区别:(1)包含可以含有多个独立的同一对象
(2)私有继承可以访问protect成员
21.私有继承
继承中默认是私有继承。
在不进行显示的转换的时候,基类的指针和引用不能指向和引用指向派生类的对象
22.使用using声名重新定义访问权限
在派生类中使用using声名将基类的特定成员即使是私有成员变成公有的
23.多重继承的两个问题
(1)两个不同的基类中继承了相同的方法
(2)从两个或者多个相关的基类那里继承了同一个类的多个实例
(1)可以通过显式的调用解决,或者从新定义一个函数。另一个现象是继承链中,存在同名函数的优先级问题。
(2) singingwaiter中存在两个worker的实体。解决方法,在类的声名中采用virtual。class singer:virtual public worker {...}
存在的问题:在构造singingwaiter的时候需要显式的构造worker,不能传递构造。
24.模板函数和模板类的区别
1.不能将模板成员函数放在独立的实现文件中
2.模板类必须显式的提供所需的类型。函数模板中可以根据参数的类型进行自动的匹配。
25.模板类中表达式参数的类型
必须是常量表达式,可以是整型、枚举、引用或者指针。不能修改参数的值,也不能使用参数的地址。
26.模板类的显式实例化、显式具体化和部分具体化
显式实例化 template class ArrayTP<String,100>
显式具体化 template<> class SortedArray<const c-har*>{};
部分具体化 template<class T1> class pair<T1,int>
27.RITTI
c++有三个支持RITTI的元素
(1)dynamic_cast.//将基类的指针和引用指向派生类。
//用途在类的层次中进行向上的转换。指针的应用中失败返回null,引用失败,抛出bad_cast异常。
(2)typeid//接受两种参数:类名、结果为对象的表达式。运算符返回一个type_info对象的引用。<typeinfo>头文件中定义了type_info类,重载了==、!=。包含有一个name方法
(3)type_info
28.const_cast、static_cast和reinterpret_cast
(1)const_cast将一个常量转换为非常量,不允许向下转换。
(2)static_cast同样不允许向上转换
(3)reinterpret_cast指针的转换
29.auto_ptr、unique和shared_ptr之间的异同点:
(1)都不允许隐式的转换
(2)unique、auto_ptr内部相互赋值时采用所有权转让的方式。shared_ptr采用采用引用计数的方式。
(3)unique为什么优与auto_ptr?在赋值后。unique可以在编译阶段报错。 unique可以允许将临时对象进行所有权的转让。
(4)使用new分配内存才能使用auto_ptr和shared_ptr,使用new[]分配的时候采用unique。