C++虚函数和多态

2021/12/6 1:20:09

本文主要是介绍C++虚函数和多态,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

虚函数和虚函数表

  1. 虚函数:用virtual修饰的成员函数
  2. 虚函数对于类的影响:增加一个指针,32位4个字节,64位8个字节
  3. 虚函数表:一个指针储存所有虚函数的首地址

虚函数和多态

多态:同一种行为(调用)产生的不同结果

多态必要性原则:

  • 父类必须存在虚函数
  • 子类必须采用public继承
  • 必须存在指针的使用
    #include<iostream>
    using namespace std;
    class Ins{
    public:
    	void func(){
    		cout << "你好!" << endl;
    	}
    	virtual void func1(){
    		cout << "他好!" << endl;
    	}
    protected:
    };
    class Owe:public Ins
    {
    public:
    	void func(){
    		cout << "你不好!" << endl;
    	}
    	void func1(){
    		cout << "他不好!" << endl;
    	}
    protected:	
    };
    int main(){
    	//有virtual看对象类型,没virtual看指针类型
    	Ins* i = new Owe;
    	i->func();//不是虚函数
    	i->func1();//虚函数
    	i = new Ins;
    	i->func1();
    	while (1);
    	return 0;
    }

输出如图结果: 

多态的作用:可以减少在源代码基础上修改,而是改为增加代码来达到所要的效果

纯虚函数和ADT

纯虚函数:是没有函数体的虚函数

作用:做ADT(abstract data type抽象数据类型)过程

在类中的写法:

virtual void function()=0;

抽象类:具有至少一个纯虚函数的类叫抽象类 

  • 抽象类不能构造对象
  • 抽象类可以构造对象指针
    #include<iostream>
    using namespace std;
    class stack{
    public:
    	virtual void push(int data) = 0;
    	virtual void pop() = 0;
    	virtual int top()const = 0;
    	virtual bool empty()const = 0;
    	virtual int size()const = 0;
    protected:
    
    };
    //子类要想创建对象必须重写父类的纯虚函数
    //ADT过程:具有强迫性,所有子类重写函数必须与父类一样
    class arrayStack :public stack{
    public:
    	void push(int data){};
    	void pop(){};
    	int top()const{ return 1; };
    	bool empty()const { return true; };
    	int size()const{ return 1; };
    protected:
    };
    class listStack :public stack{
    public:
    	void push(int data){};
    	void pop(){};
    	int top()const{ return 1; };
    	bool empty()const { return true; };
    	int size()const{ return 1; };
    protected:
    };
    void testStack(stack* p){
    	p->push(0);
    	while (!p->empty()){
    		cout << p->top() << endl;
    		p->pop();
    	}
    }
    int main(){
    	testStack(new arrayStack);
    	testStack(new listStack);
    	while (1);
    	return 0;
    }

纯虚析构函数

在用子类对象初始化父类指针的时候,父类需要写虚析构函数做内存的释放

#include<iostream>
using namespace std;
class parent{
public:	
	//virtual ~parent(){
	//	cout << "父类" << endl;
	//}
protected:
};
class kid:public parent{
public:
	~kid(){
		cout << "子类" << endl;
}
protected:
};
int main(){
	parent* ptr = new kid;
	delete ptr;
	ptr = nullptr;
	while (1);
	return 0;
}

 final和override

final和override:final :禁止重写(只在继承中使用),只能用于虚函数和,子类不能存在同名函数,override强制重写,标识作用,检查父类中是否存在当前虚函数

class parent{
public:
	virtual void func() final{}
	virtual void func1(){}
protected:
};
class child:public parent{
public:
	//不能使用与父辈同名的函数void func(){};
	void func1()override{}//标识作用,如果父类不存在同名虚函数就会报错
protected:
};

C++类型转换

格式:  关键字  _cast<要转换的类型>(要转换的目标)

  • const_cast:作用:1.去掉const属性(提供一个接口操作const属性)    2.加上const属性
        int num=1;
    	const int&p = num;
    	int&pp = const_cast<int&>(p);//去掉const属性
    	int a = 5;
    	int*ptr = &a;
    	const int*pr = const_cast<const int*>(ptr);//加上const属性,用的比较少,不写const_cast也可以隐式转换,即:const int*pr=ptr;
    

  • static_cast:

1.基本数据类型转换

2.把空指针转换成相应类型指针

3.把任何类型变量转化成void类型

4.用在基类和派生类的对象之间的转换:

     进行上行转换(从子到父,指针或引用转换)

     进行下行转换(从父到子,指针或引用转换)

注:static_cast不能用于去掉const

  • dynamic_cast:

1.上行转换(和static_cast一样)

2.下行转换(dynamic更安全)

#include<iostream>
#include<string>
using namespace std;
class parent{
public:
	virtual void print(){ cout << str << endl; }
protected:
	string str = "ILoveYou!";
};
class child:public parent{
public:
	void print(){ cout << str1 << endl; }
protected:
	string str1 = "Hello!";
};
int main(){
	parent* p=new parent;
	child* q=new child;
	//上行转换
	parent* l = static_cast<parent*>(q);
	parent* u = dynamic_cast<parent*>(q);
	l->print();
	u->print();
	//下行转换
	child* h = static_cast<child*>(p);
	child* k = dynamic_cast<child*>(p);//dynamic可以检验父类中是否存在多态
	if (k!=nullptr)
		k->print();
	h->print();
	while (1);
	return 0;
}

3.交叉转换(多继承)

#include<iostream>
using namespace std;
class A{
public:
	virtual void print(){ cout << 'A'<<endl ;}
protected:
};
class B{
public:
	virtual void print(){ cout << 'B' << endl; }
protected:
};
class C:public A,public B{
public:
	void print(){ cout << 'C' << endl; }
protected:
};
int main(){
	//交叉转换
	A* a = new C;
	B* b = dynamic_cast<B*>(a);
	b->print();
	while (1);
	return 0;
}
  • reinterpret_cast:把数转换成指针,把指针转换成数
    #include<iostream>
    using namespace std;
    int Max(int a, int b)
    {
       return a > b ? a : b;
    }
    int main(){
    	int num = reinterpret_cast<int>(Max);
    	cout << num << endl;
    	cout << Max << endl;
    	auto p = reinterpret_cast<int(*)(int a, int b)>(num);
    	cout << p(1, 2) << endl;
    	while (1);
    	return 0;
    }



这篇关于C++虚函数和多态的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程