C++ 快速回顾(四)

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;
}

你可能感兴趣的:(C++,c++)