C++ 快速回顾(四)
- 前言
- 一、纯虚函数
- 二、final关键字
- 1.作用到函数
- 2.作用到类
- 三、虚函数原理
- 四、Lambda一些知识补充
前言
用于快速回顾之前遗漏或者补充C++知识
一、纯虚函数
纯虚函数主要是当接口,没有具体的实现要到派生类去实现。
- 纯虚函数不能直接实例化,类似c#中的抽象函数
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};int main()
{//MyClassBase Base; 不能实例化system("pause");return 0;
}
- 纯虚函数的派生类,必须实现了纯虚函数才能实例化
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{};int main()
{//MyClass Class; 不能实例化system("pause");return 0;
}
- 正确的使用方式
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override{}
};int main()
{MyClass Class; // 可以实例化system("pause");return 0;
}
二、final关键字
final 主要是处理不想继续往下派生,禁止往下派生的情况
很像C#中的密封
1.作用到函数
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override final{}
};class ChildClass : public MyClass
{
public:virtual void Init() override{}// 无法重写//virtual void Destroy() override//{////}
};
2.作用到类
无法继续派生,不能用final类作为基类
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass final : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override{}
};// 无法继续派生,不能用final类作为基类
class ChildClass : public MyClass
{};
三、虚函数原理
要弄懂这个问题,我们要从最基本的类的内存大小来看
下面的这个空类,所占的大小是1字节,可以说这一字节是用来占位的
class MyClass
{};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
可以看到当有个int类型的变量后大小变为了4
class MyClass
{int Value = 0;
};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
那如果加个函数大小会有什么变化?答案是仍然为4
class MyClass
{int Value = 0;void Init() {}
};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
如果我们写个虚函数可以发现大小变成了16
class MyClass
{virtual void Init(){}
};class MyClass1 : public MyClass
{int a = 0;
};int main()
{int size = sizeof(MyClass1);std::cout << size << std::endl;system("pause");return 0;
}
那这时候我们写多个虚函数呢?答案也是16,可以看到只要有一个虚函数之后再有多少个虚函数大小都是16了。
当我们有虚函数时编辑器会为其生成虚函数表指针(vptr) 这个虚函数表指针会指向一个虚函数表,里面存储着虚函数,当我们复写时会覆盖表中的函数导致重写后调用了新的函数。
但是为什么大小是16呢?因为在64位操作系统中虚函数表指针(vptr) 占8个字节,4+8 = 12 也不是16 ? 这是因为内存对齐的缘故通常8字节对齐。所以就是16字节了。
class MyClass
{virtual void Init(){}virtual void Init1(){}virtual void Init2(){}virtual void Init3(){}
};class MyClass1 : public MyClass
{int a = 0;
};int main()
{int size = sizeof(MyClass1);std::cout << size << std::endl;system("pause");return 0;
}
四、Lambda一些知识补充
一般的Lambda就不细讲了,只补充不知道的知识
注意这里不能直接传入,是因为Lambda传入的buffer 是加个Const的
int main()
{char buffer[1024] = "Hello World !!!";auto Test = [buffer](char* Value1){auto Test1 = [](char* Value2){printf(Value2);};Test1(buffer); // 注意这里不能直接传入,是因为Lambda传入的buffer 是加个Const的};system("pause");return 0;
}
加个const 即可
int main()
{char buffer[1024] = "Hello World !!!";auto Test = [buffer](char* Value1){auto Test1 = [](const char* Value2){printf(Value2);};Test1(buffer);};system("pause");return 0;
}