概述
学了一阵子感觉这个东西特别绕,记录下自己的理解,当然如果理解错了!请各位指出来,感激!
c++中的虚函数:
同一个类型的指针(基类指针),指向不同类型的对象(派生类),调用同一函数(虚函数),实现不同的功能(函数实现)
虚函数都存储在一个表中,相同类型的虚函数(同一个基类派生出来的),这些函数在续表中的映射地址是相同的,函数地址当然不同(当派生类中的虚函数被重载)。
而虚函数的地址也是可以被输出显示的:显示规则如下:此段代码以及解释转载自:chick here
#include <iostream>
#include <stdio.h>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
void h() { cout << "Base::h" << endl; }
};
class hehe:public Base{
virtual void haha(){
cout << "rnrn" << endl;
}
void f(){
cout << "haha" << endl;
}
};
typedef void(*Fun)(void); //函数指针
int main()
{
Base b;
hehe c;
// 这里指针操作比较混乱,在此稍微解析下:
// *****printf("虚表地址:%pn", *(int *)&b); 解析*****:
// 1.&b代表对象b的起始地址
// 2.(int *)&b 强转成int *类型,为了后面取b对象的前四个字节,前四个字节是虚表指针
// 3.*(int *)&b 取前四个字节,即vptr虚表地址
//
// *****printf("第一个虚函数地址:%pn", *(int *)*(int *)&b);*****:
// 根据上面的解析我们知道*(int *)&b是vptr,即虚表指针.并且虚表是存放虚函数指针的
// 所以虚表中每个元素(虚函数指针)在32位编译器下是4个字节,因此(int *)*(int *)&b
// 这样强转后为了后面的取四个字节.所以*(int *)*(int *)&b就是虚表的第一个元素.
// 即f()的地址.
// 那么接下来的取第二个虚函数地址也就依次类推. 始终记着vptr指向的是一块内存,
// 这块内存存放着虚函数地址,这块内存就是我们所说的虚表.
//
printf("虚表地址:%pn", *(int *)&b);
printf("第一个虚函数地址:%pn", *(int *)*(int *)&b);
printf("第二个虚函数地址:%pn", *((int *)*(int *)(&b) + 1));
printf("第一个虚函数地址:%pn", *(int *)*(int *)&c);
printf("第二个虚函数地址:%pn", *((int *)*(int *)(&c) + 1));
//Fun pfun = (Fun)*((int *)*(int *)(&b)); /itural f();
//printf("f():%pn", pfun);
//pfun();
//pfun = (Fun)(*((int *)*(int *)(&b) + 1)); /itural g();
//printf("g():%pn", pfun);
//pfun();
}
举个例子,异质单链表的简单构成: 同一链表中,存储不同类型的信息(1.学生类的信息 2。老师类的信息)
先定义person类,构造print 的虚函数,之后派生出 学生和老师类,在链表中,指针的类型为person(基类),而输出时候,便可以调用虚函数来实现输出不同的结果。
代码例子如下:
#include <iostream>
#include <stdio.h>
using namespace std;
class List;
class person
{
friend class List;
public:
person(int _age, char *s)
{
age=_age;
name=s;
Next=NULL;
}
virtual ~person() {};
virtual void print()
{
cout<<" name is "<<name<<endl;
cout<<" age is "<<age<<endl;
}
protected:
int age;
char *name;
person* Next;
};
class teacher:public person
{
public:
teacher(int _age,char *s,int _title):person(_age,s)
{
title=_title;
}
void print()
{
person::print();
cout<<" title is "<<title<<endl;
}
protected:
int title;
};
class student:public person
{
public:
student(int _age,char *s,int _number):person(_age,s)
{
number=_number;
}
virtual void print()
{
person::print();
cout<<" number is "<<number<<endl;
}
void sp()
{
cout<<"gggg"<<endl;
}
protected:
int number;
};
class List
{
private:
person * head;
int siz;
public:
List()
{
head=NULL;siz=0;
}
void Insert(person *p)
{
person *tmp=head;
if(head==NULL)
{
head=p;
}
else
{
while(tmp->Next!=NULL)
{
tmp=tmp->Next;
}
tmp->Next=p;
}
siz++;
}
void show()
{
person *tmp=head;
if(head==NULL)
{
cout<<"No one"<<endl;
return ;
}
while(tmp!=NULL)
{
tmp->print();
tmp=tmp->Next;
}
}
};
int main(void)
{
List root;
char a[20]="abc";
char b[20]="def";
teacher prof1( 40,a ,2);
student prof2( 50,b, 4);
root.Insert(&prof1 ); //把prof1插入到personList中
root.Insert(&prof2 ); //把prof2插入到personList中
root.show(); //输出personList各结点的数据域值
}
最后
以上就是爱撒娇棉花糖为你收集整理的C++中虚函数的全部内容,希望文章能够帮你解决C++中虚函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复