C++虚函数与多态
C++虚函数与多态
- 虚函数
- 抽象类
- 纯虚函数
- 虚析构函数
- 多态
- 虚函数的几个问题
- 纯虚函数和ADT
虚函数
virtual修饰的成员函数就是虚函数,
1.虚函数对类的内存影响:增加一个指针类型大小(32位和64位)
2.无论有多少个虚函数,只增加一个指针类型虚函数表:指向虚函数的指针(监视的窗口看)
我们自己也可以通过虚函数指针表去访问函数(一般做这样的说数据操作,不写数据类型)
include<iostream>
#include<string>
using namespace std;
class MM
{
public:
virtual void print()
{
cout << "第一个虚函数" << endl;
}
virtual void printDate()
{
cout << "第二个虚函数" << endl;
}
private:
int age;
string name;
};
int main()
{
cout << sizeof(MM) << endl;
system("pause");
return 0;
}
抽象类
拥有一个或一个以上的纯虚函数就被叫做抽象类
特点:
1.抽象类不能够创建对象
2.抽象类可以创建对对象指针
纯虚函数
纯虚函数也是一个虚函数,所以也需要virtual来修饰
特点:
1.纯函数没有函数体
所以函数 = 0;
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
virtual void print() = 0; //纯虚函数
private:
int age;
};
int main()
{
//MM mm; //抽象类不能够构造对象
MM* pmm = nullptr;
return 0;
}
虚析构函数
在析构函数前面加一个virtual
1.当父类指针对子类对象进行初始化的时候,就要用虚析构函数
2.所有析构函数底层解析的话。函数名想相同
include<iostream>
#include<string>
using namespace std;
class MM
{
public:
void print()
{
cout << "MM" << endl;
}
~MM()
{
cout << "MM析构" << endl;
}
protected:
string M_name;
};
class son : public MM
{
public:
void print()
{
cout << "son" << endl;
}
~son()
{
cout << "son析构" << endl;
}
};
int main()
{
MM* p = new son; //父类指针,构造子类对象,先构造父类对象,在构造子类的对象
delete p;
system("pause");
return 0;
}
只调用了父类的析构函数,没有调用子类的析构函数,存在内存的泄露。
所以用父类指针初始化子类的对象,必须使用虚虚构函数
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
void print()
{
cout << "MM" << endl;
}
virtual ~MM()
{
cout << "MM析构" << endl;
}
protected:
string M_name;
};
class son : public MM
{
public:
void print()
{
cout << "son" << endl;
}
~son()
{
cout << "son析构" << endl;
}
};
int main()
{
MM* p = new son; //父类指针,构造子类对象,先构造父类对象,在构造子类的对象
delete p;
system("pause");
return 0;
}
多态
多态:在继承中,指针的同一行为的不同结果
多态的概念其实并不重要,重要的是,你需要知道,那个对象指针在特定情况调用那个成员。
实现多态的2个条件
1.必须是public继承
2.必须父类存在virtual类型的成员函数,并且子类中存在该函数的同名函数。
3.一定存在对象的引用
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
void print()
{
cout << "MM" << endl;
}
virtual void printDate()
{
cout << "virtual printDate" << endl;
}
virtual ~MM()
{
cout << "MM析构" << endl;
}
protected:
string M_name;
};
class son : public MM
{
public:
void print()
{
cout << "son" << endl;
}
void printDate()
{
cout << "printDate" << endl;
}
~son()
{
cout << "son析构" << endl;
}
};
int main()
{
//MM* p = new son; //父类指针,构造子类对象,先构造父类对象,在构造子类的对象
//delete p;
MM* p = new son;
p->print(); // 没有virtual,看指针类型,这里调用的是父类的
p->printDate(); //有virtual,看对象,这里调用的是son的
p = new MM; //调用MM 的 这就是多态
p->print();
//引用的类型也存在多态
MM mm;
MM& girl = mm;
mm.printDate();
system("pause");
return 0;
}
虚函数的几个问题
不管被继承几次,父类中有的虚函数,依然存在
#include<iostream>
using namespace std;
class A
{
public:
virtual void print()
{
cout << "A" << endl;
}
};
class B : public A
{
public:
};
class C : public B
{
public:
void print()
{
cout << "C" << endl;
}
};
int main()
{
A* p = new C;
p->print();
system("pause");
return 0;
}
子类实现父类虚函数的同名函数叫做:重写
final :静止重写(子类中不允许存在与之同名的虚函数)
override :强制重写,起说明作用,表示子类当前是方法是重写父类(就是说明父类中一定存在一个同名的虚函数),用于子类实现父类的同名虚函数
#include<iostream>
using namespace std;
class A
{
public:
virtual void print() final //final:静止重写,子类中不能够存在同名函数
{
}
virtual void printDate()
{
}
};
class B : public A
{
public:
void printDate() override // 强制重写,起说明作用,表示子类当前是方法是重写父类(就是说明父类中一定存在一个同名的虚函数)
{
}
};
int main()
{
system("pause");
return 0;
}
纯虚函数和ADT
ADT:抽象数据类型
注意:抽象类本身不能够创建对象,但是抽象类的子类可以创建对象
抽象类,一般用于架构项目,构建好整个项目模块,具体的细致工作,交给子类去实现采用ADT的方式设计项目,可以把这个模块构建出来,并且测试代码也可以提前完成。