C++之template之类相关
template之类相关虚函数模板在我们使用模板从来都没有将虚函数与模板进行套用, 那么这两者能不能同时连用呢?
这个直接来写代码验证才知道.
123456789class point {public: template <class T> virtual T getX() { return x; }private: int x;};int main() { exit(0); }
分别用了g++和clang编译
123456// g++virtual_template.cpp:17:4: error: templates may not be ‘virtual’ virtual T getX()// clangvirtual_template.cpp:17:4: error: 'virtual' cannot be specified on member function templates virtual T getX()
可以看出来 ...
C++之template
templatetemplate的使用大大提高了代码的复用性, 抽象性
类模板实例化时并不是每个成员函数都实例化了, 而是使用到了哪个成员函数, 那个成员函数才实例化
1234567891011121314151617181920212223/* ***** 1 *******/template<class T>class point{ public: point() : x(0), y(0) {} point(T x, T y) : x(x), y(y) {} T getX() const { x = y; return x; } // 一般是无法通过编译的, x不允许被修改, 但是这里并没有报错 private: T x; T y;};/* ***** 2 *******/#define T intclass point{ public: point() : x(0), y(0) {} point(T x, T y) : x(x), y( ...
C++之虚函数的vptr和vtable
虚函数的vptr与vtable为了实现虚函数,C ++使用一种称为虚拟表的特殊形式的后期绑定。该虚拟表是用于解决在动态/后期绑定方式的函数调用函数的查找表。虚拟表有时会使用其他名称,例如“vtable”,“虚函数表”,“虚方法表”或“调度表”。
首先,每个使用虚函数的类(或者从使用虚函数的类派生)都有自己的虚拟表。该表只是编译器在编译时设置的静态数组。虚拟表包含可由类的对象调用的每个虚函数的一个条目。此表中的每个条目只是一个函数指针,指向该类可访问的派生函数。
其次,编译器还会添加一个隐藏指向基类的指针,我们称之为vptr。vptr在创建类实例时自动设置,以便指向该类的虚拟表。与this指针不同,this指针实际上是编译器用来解析自引用的函数参数,vptr是一个真正的指针。
因此,它使每个类对象的分配大一个指针的大小。这也意味着vptr由派生类继承,这很重要。
实现与内部结构
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 ...
C++之纯虚函数和抽象类
纯虚函数和抽象类纯虚函数与抽象类C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数!
123456789// 抽象类class Test { // Data members of classpublic: // Pure Virtual Function virtual void show() = 0; /* Other members */};
纯虚函数:没有函数体的虚函数
抽象类:包含纯虚函数的类
1234567891011121314151617181920212223#include<iostream>using namespace std;class A{private: int a;public: virtual void show()=0; // 纯虚函数};int main(){ /* * 1. 抽象类只能作为基类来派生新类使用 * 2. 抽象类的指针和引用->由抽象类派生出来的类的对象! */ ...
字节对齐详解
字节对其详解什么是字节对齐123456789101112#include<stdio.h>struct{ int x; char y;} s;int main(){ printf("%d\n",sizeof(s)); // 输出8 return 0;}
计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,计算机并非逐字节大小读写内存,而是以2,4,或8的 倍数的字节块来读写内存,如此一来就会对基本数据类型的合法地址作出一些限制,即它的地址必须是2,4或8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。
对齐准则
结构体变量的首地址能够被其对齐字节数大小所整除。
结构体每个成员相对结构体首地址的偏移都是成员大小的整数倍,如不满足,对前一个成员填充字节以满足。
结构体的总大小为结构体对齐字节数大小的整数倍,如不满足,最后填充字节以满足。
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。gcc中默认 ...
C++之this详解
this详解this的用处:
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。
this作用域时在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含行参,对各成员的访问均可通过this访问。
其次,this指针的使用:
在类的非静态成员函数中返回类对象本身的时候,直接使用return *this。
当参数与成员变量名相同时,如this->n = n (不能写成n = n)。
12345678910111213141516171819202122232425262728293031323334353637#include <cstring>#include <iostream>using namespace std;class Person {public: typedef enum { BOY = 0, GIRL ...
C++之static详解
static详解使用static关键字:
静态变量: 函数中的变量,类中的变量
静态类的成员: 类对象和类中的函数
静态变量
函数中的静态变量
当变量声明为static时,空间将在程序的生命周期内分配。即使多次调用该函数,静态变量的空间也只分配一次,前一次调用中的变量值通过下一次函数调用传递。
123456789101112131415161718192021#include <iostream>#include <string>using namespace std;void demp() { // static variable static int count = 0; cout << count << " "; // value is update and will be carried to next function calls count++;}int main() { for (int i = 0; i < 5; i++) { demp( ...
C++之inline详解
inline详解类中内联头文件中声明方法
1234567891011121314151617class A{public: void f1(int x); /** * @brief 类中定义了的函数是隐式内联函数,声明要想成为内联函数,必须在实现处(定义处)加inline关键字。 * * @param x * @param y */ void Foo(int x,int y) ///< 定义即隐式内联函数! { }; void f1(int x); ///< 声明后,要想成为内联函数,必须在定义处加inline关键字。 };
实现文件中定义内联函数:
123456789101112131415161718192021222324252627282930313233343536#include <iostream>#include "inline.h"using namespace std;/** * @brief inli ...
C++之sizeof详解
sizeof 详解类大小计算
空类的大小为1字节
一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。
对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
普通继承,派生类继承了所有基类的函数与成员,要按照字节对齐来计算大小
虚函数继承,不管是单继承还是多继承,都是继承了基类的vptr。(32位操作系统4字节,64位操作系统 8字节)!
虚继承,继承基类的vptr。
原则1空类的大小为1字节
1234567891011// 空类的大小为1字节#include <iostream>using namespace std;class A {};int main() { cout << sizeof(A) << endl; return 0;}
原则2静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据 ...
C++之Const详解
Const详解const含义常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。
const作用
可以定义常量
1const int a=100;
类型检查
const常量与#define宏定义常量的区别: const常量具有类型,编译器可以进行安全检查;#define宏定义没有数据类型,只是简单的字符串替换,不能进行安全检查。
防止修改,起保护作用,增加程序健壮性
123void f(const int i){ i++; //error!}
可以节省空间,避免不必要的内存分配
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
const对象默认为文件局部变量非const变量默认为extern。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern
未被const修饰的变量在不同文件的访问:
12345678910111213// ...



