1 虚函数与虚函数表
虚函数:用virtual修饰的成员函数
虚函数表:就是一个指针存储所有虚函数的首地址
#include <iostream>
using namespace std;
class student
{
public:
void print()//普通函数不影响类的内存
{
cout << "普通函数" << endl;
}
virtual void print1()//虚函数类的内存增加,不论几个增加不变
{//32位操作系统增加4字节,64位8字节
cout << "虚函数" << endl;
}
virtual void print2()
{
cout << "虚函数2" << endl;
}
virtual void print3();
protected:
};
void student::print3()
{
cout << "在类内定义虚函数,在类外实现" << endl;
}
void testVirtual()
{//C语言不允许存在空的结构体
cout << sizeof(student) << endl;
student A;
int** vptr = (int**)&A;
typedef void(*PF)();
PF func = (PF)vptr[0][0];
func();//虚函数表调用第一个虚函数
func = (PF)vptr[0][1];
func();//虚函数表调用第二个虚函数
}//C++允许存在空的类或结构体,占1字节
int main()
{
testVirtual();
return 0;
}
2虚函数和多态
定义:同一个调用的不同结果为多态
必要性原则:父类必须存在虚函数,子类必须采用公有继承 ,必须存在指针的引用。
class student
{
public:
void print1()
{
cout << "是学生1" << endl;
}
virtual void print2()//父类必须有virtual
{
cout << "是学生2" << endl;
}
protected:
};
class teacher:public student//公有继承
{
public:
void print1()
{
cout << "是老师1" << endl;
}
void print2()//子类要存在一个同名函数
{
cout << "是老师2" << endl;
}
protected:
};
void testVirtual()
{
//正常访问不存在多态,就近原则
student A;
A.print1();
A.print2();
teacher B;
B.print1();
B.print2();
//指针访问,正常赋值
student* ps = new student;
ps->print1();
ps->print2();
teacher* pt = new teacher;
pt->print1();
pt->print2();
//指针非正常赋值:子类对象初始化父类指针
student* Ps = new teacher;
Ps->print1();//非虚函数
Ps->print2();//虚函数,父类调用子类同名函数
}
3 纯虚函数与ADT
纯虚函数也是一个虚函数,但没有函数体
抽象类:具有至少一个纯虚函数的类
抽象类不能构建对象,但可以构建对象指针
class parent
{
public:
virtual void print() = 0;//纯虚函数写法
protected:
};
void textVirtual()
{
//parent A;//报错抽象类不能构建对象
parent* P = nullptr;//可以构建指针
}
//纯虚函数就是做ADT(abstract data type)抽象数据类型的额过程
class stack
{
public://父类中描述好所有的属性
virtual void push(int data) = 0;
virtual void pop() = 0;
virtual void top()const = 0;
virtual bool empty()const = 0;
virtual int size() = 0;
};
class arryStack :public stack
{
public:
};
class listStack :public stack
{
public:
};
4 虚析构函数
class parent
{
public:
virtual ~parent()
{
cout << "父类析构" << endl;
}
void print()
{
}
protected:
};
class son:public parent
{
public:
~son()
{
cout << "子类析构" << endl;
}
void print()
{
}
protected:
};
int main()
{//在用子类初始化父类指针,父类需要析构函数做内存释放
parent* P = new son;
P->print();
delete P;
P = nullptr;
return 0;
}
5 C++类型转换与两个关键字
//两个关键字 final override
class A
{
public:
virtual void print()final//
{//加final后子类不能存在同名函数
//限制子类不能重写这个函数
//孙子类也不行!!
cout << "重写虚函数才有" << endl;
}
virtual void printData()
{
}
protected:
};
class B :public A
{
public:
//void print()
void printData()override
{//强制重写标识作用,用于检查父类是否存在当前的虚函数
cout << "表示当前函数是重写函数" << endl;
}
};
class A
{
public:
A(const char* str) :str(const_cast<char*>(str)) {}
protected:
char* str;
};
class B
{
public:
B(int num) :num(num) {}
protected:
int num;
};
int main()
{
//const_cast
//const_cast<要转换的类型>(要转换的目标)
//作用1去掉const属性 2加上const属性
const int num = 9;
int* Pnum = const_cast<int*>(&num);
*Pnum = 99;
cout << num << endl;
A a("jsbd");
char c[] = "lskd";
A b(c);
const B* pB = new B(0);
B* Pb = const_cast<B*>(pB);
int num;
const int& pnum = num;
int& Pnum = const_cast<int&>(pnum);
int a1 = 99;
int* Pa = &a1;
const int* pA = Pa;
//static_cast
//static_cast<要转换的类型>(要转换的目标)
//基本数据类型转换,把任何类型的变量转换为void类型
//用在类上面改的转换(基本和派生类对象之间的转换)
char str = 'A';
int istr = static_cast<int>(str);
cout << istr << endl;
double* pD = new double;
void* pD1 = static_cast<void*>(pD);
return 0;
}