C++零散知识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mingfengshan/article/details/79246708

1、volatile关键字:
提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

2、new关键字:
new 关键字创建对象时,对于内置类型:加括号会初始化,不加括号不初始化;对于自定义类型,都会调用默认构造函数,加不加括号没区别。

3、C++ 的Virtual的用法:
(1)虚函数:类Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在Base的派生类Derived中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。当基类Base的指针point指向派生类Derived的对象时,对point的print函数的调用实际上是调用了Derived的print函数而不是Base的print函数。这是面向对象中的多态性的体现。
注意:基类的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的。
(2)纯虚函数:C++语言为我们提供了一种语法结构,通过它可以指明,一个虚拟函数只是提供了一个可被子类型改写的接口。但是,它本身并不能通过虚拟机制被调用。这就是纯虚拟函数(purevirtual function)。
注意:包含一个或多个纯虚拟函数的类被编译器识别为抽象基类。抽象基类不能被实例化,一般用于继承。
(3)虚拟继承(virtual public):在多继承下,虚继承就是为了解决菱形继承中,B,C都继承了A,D继承了B,C,那么D关于A的引用只有一次,而不是普通继承的对于A引用了两次。格式:可以采用public、protected、private三种不同的继承关键字进行修饰,只要确保包含virtual就可以了。
虚继承:在继承定义中包含了virtual关键字的继承关系;
虚基类:在虚继承体系中的通过virtual继承而来的基类。
注意:C++标准中(也是很自然的)选择在每一次继承子类中都必须书写初始化语句(因为每一次继承子类可能都会用来定义对象),而在最下层继承子类中实际执行初始化过程。所以上面在每一个继承类中都要书写初始化语句,但是在创建对象时,而仅 仅会在创建对象用的类构造函数中实际的执行初始化语句,其他的初始化语句都会被压制不调用。

4、 static 关键字的用途:
C 语言的 static 关键字有三种(具体来说是两种)用途:

  1. 静态局部变量:用于函数体内部修饰变量,这种变量的生存期长于该函数。对于一个完整的程序,在内存中的分布情况如下图: 
    (1)栈区: 由编译器自动分配释放,像局部变量,函数参数,都是在栈区。会随着作用于退出而释放空间。
    (2)堆区:程序员分配并释放的区域,像malloc©,new(c++) 。
    (3)全局数据区(静态区):全局变量和静态便令的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。
    (4)代码区。
    note:1的static是在全局数据区分配的:它存在的意义就是随着第一次函数的调用而初始化,却不随着函数的调用结束而销毁。那么第二个问题也就浮出水面了,它是在第一次调用函数的时候初始化。且只初始化一次,也就是你第二次调用函数,不会继续初始化,而会直接跳过。
    那么它跟定义一个全局变量有什么区别呢,同样是初始化一次,连续调用函数的结果是一样的,但是,使用全局变量的话,变量就不属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。静态局部变量正好可以解决这个问题。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
    总结:
    (1)该变量在全局数据区分配内存(局部变量在栈区分配内存);
    (2)静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化(局部变量每次函数调用都会被初始化);
    (3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0(局部变量不会被初始化);
    (4)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,也就是不能在函数体外面使用它(局部变量在栈区,在函数结束后立即释放内存);
    2.静态全局变量:定义在函数体外,用于修饰全局变量,表示该变量只在本文件可见:
    静态全局变量不能被其它文件所用(全局变量可以);
    其它文件中可以定义相同名字的变量,不会发生冲突(自然了,因为static隔离了文件,其它文件使用相同的名字的变量,也跟它没关系了);
    3.静态函数:准确的说,静态函数跟静态全局变量的作用类似。所以,静态函数的好处跟静态全局变量的好处就类似了:
    1.静态函数不能被其它文件所用;
    2.其它文件中可以定义相同名字的函数,不会发生冲突;

C++ 语言的 static 关键字有二种用途:
当然以上的几种,也可以用在c++中。还有额外的两种用法:
1.静态数据成员:用于修饰 class 的数据成员,即所谓“静态成员”。这种数据成员的生存期大于 class 的对象(实体 instance)。静态数据成员是每个class 有一份,普通数据成员是每个 instance 有一份,因此静态数据成员也叫做类变量,而普通数据成员也叫做实例变量。
2、静态成员函数:用于修饰 class 的成员函数。那么静态成员函数有特点呢?
(1)静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
(2)非静态成员函数可以任意地访问静态成员函数和静态数据成员;
(3)静态成员函数不能访问非静态成员函数和非静态数据成员;
(4)调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以用类名::函数名调用(因为他本来就是属于类的,用类名调用很正常)。
重点:静态成员函数访问非静态成员方法:
1、有一个很取巧的办法,就是在静态函数的形参表里加上实例的地址,也就是
class A
{
public:
static void test(A *a)
{
a->m_a += 1;
}
void hello()
{
}
private:
static int m_staticA;
int m_a
};
这样在你回调函数的时候,你可以通过这个来让本身不能访问成员非静态变量的静态函数(太拗口)来访问非静态成员变量。
2、大家都知道静态成员函数不能访问非静态成员,但别忘了,他们可以访问静态成员,也就是说,如果我们的这个类是个单例,我们完全可以在创建的时候把this指针赋值给那个静态成员,然后在静态成员函数内部就可以放心大胆的使用了。
class A
{
public:
A()
{
m_gA = this;
}
static void test()
{
m_gA.m_a += 1;
}
void hello()
{
}
private:
static int m_staticA;
static A *m_gA;
int m_a
};
3、和方法一比较像,但他的方向思想更多的是针对内存块这个概念,意思就是在静态函数的形参比加上一个void *的内存首地址,然后在内部做转换
class A
{
public:
static void test(void *pData)
{
A *a = (A *)pData;
a->m_a += 1;
}
void hello()
{
}
private:
static int m_staticA;
int m_a
};
A a;
test(&a);

5、default”标签跳过“ ”的初始化操作问题:
原因是在switch 中有初始化的工作。在switch 语句中不可以有定义部分。如果有定义,如初始化的时候,必须把定义部分需要用{ } 括起来。

6、static和const的作用:
static的作用:
1). 静态局部变量:用于函数体内部修饰变量,这种变量的生存期长于该函数。
2).静态全局变量:定义在函数体外,用于修饰全局变量,表示该变量只在本文件可见。
3).静态函数:准确的说,静态函数跟静态全局变量的作用类似,所以,静态函数的好处跟静态全局变量的好处就类似了。
4).静态数据成员:用于修饰 class 的数据成员,即所谓“静态成员”。这种数据成员的生存期大于 class 的对象(实体 instance)。静态数据成员是每个class 有一份,普通数据成员是每个 instance 有一份,因此静态数据成员也叫做类变量,而普通数据成员也叫做实例变量。
5).静态成员函数:用于修饰 class 的成员函数。

const的作用:
1、定义常量,使变量不可被改变,注意需先初始化。
2、定义指针本身为常量,定义指针所指向的内容不可改变。
3、在函数中可修饰形参,使其在函数内部不可改变。

7、指针和引用的区别:
1).指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
2).引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化。
3).可以有const指针,但是没有const引用。
4).指针可以有多级,但是引用只能是一级。
5).指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。
6).”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小。
7).指针和引用的自增(++)运算意义不一样。
8).程序为指针变量分配内存区域,而引用不需要分配内存区域。
9).指针和引用作为函数参数进行传递时也不同。用指针传递参数,可以实现对实参进行改变的目的;在将引用作为函数参数进行传递时,实质上传递的是实参本身,而不是实参的一个拷贝,因此对形参的修改其实是对实参的修改。

猜你喜欢

转载自blog.csdn.net/mingfengshan/article/details/79246708