C/C++的一些知识点 一些内容经常会被遗忘 现在就不定时的记录下来
关键字
explicit(Explicit Call to a Constructor)
明确不希望被 隐式调用(Implicit Call to a Constructor)
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1=12;//隐式调用其构造函数,成功
Test2 t2=12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
volatile
为什么要用volatile
编译器发现2次从n读数据的代码之间 没有对n进行过操作 就会自动使用上次读的数据
如果加上volatile 就相当于告诉编译器 访问该变量时不再进行优化 从而能够稳定的访问变量n
什么情况下会出现这类问题
1.汇编代码修改变量
#include <stdio.h>
void main()
{
int i = 10; --> volatile int i = 10;
int a = i;
printf("i = %d\n", a);
// 下面汇编语句的作用就是改变内存中 i 的值
// 但是又不让编译器知道
__asm
{
mov dword ptr[ebp - 4], 20h
}
int b = i;
printf("i = %d\n", b);
}
当关闭优化时 正确输出
i = 10
i = 32
开启优化时(O2…) 则输出
i = 10
i = 10
如果i使用volatile修饰符时 皆正确输出
i = 10
i = 32
2.多线程下对变量的修改 变量 stop
volatile bool stop = false;
线程1中:
while(!stop) {...}
printf("stop!");
线程2中:
stop = true
线程2后启动与线程1 若stop不加volatile 线程1将是死循环
面向对象
面向对象
封装 继承 多态
C++构造函数和析构函数是否可以为virtual
构造函数不行 析构函数可以
原因是虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的 而在构造函数完成前 虚函数表尚未创建 虚函数及虚函数表可以通过C++虚函数表解析进行深入了解
为什么要求具有层次结构的顶级类定义其析构函数为虚函数
Class A
{
public:
A(){}
~A(){printf("~A\n");} --> virtual ~A(){printf("v ~A\n");}
};
Class B: public A
{
public:
B(){}
~B(){printf("~B\n");}
}
A* a = new B();
delete a;
派生类的成员需要析构等操作时 需要调用对应的析构代码 通过对析构函数设为虚函数的方式 使得类逐层进行析构(同时也是为了防止内存泄漏)
如果析构函数非虚函数 调用的析构函数依赖于指向的静态类型
析构函数为虚函数时 输出:
~B
v ~A
析构函数非虚函数时 输出:
~A
虚函数的常见问题
1.构造函数不能是虚函数
2.析构函数可以是虚函数(甚至是纯虚函数) 具有层次结构的顶级类中往往是必须的
3.将一个函数定义为纯虚函数 则为抽象类 不能生成对象 若要使派生类为非抽象类 必须实现虚函数的函数体(一旦实现 此时纯虚函数变为虚函数)
4.派生类的override虚函数定义必须和父类完全一致 除了一个特例 如果父类中返回值是一个指针或引用 子类override时可以返回这个指针(或引用)的派生
…
未完待续…