静态联编和动态联编
1、将源代码中的函数调用解释为执行特定的函数代码被称为函数名联编
2、根据函数名选择对应的函数体执行,但是在C++有函数重载所以这必须还要看函数的参数及函数名才能确定使用那个函数
3、这个可以在编译过程就完成这种编译(静态联编)
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
void eat()
{
cout << "动物在吃饭" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
virtual void eat()
{
cout << "小猫在吃鱼" << endl;
}
};
void doSpeak(Animal & animal)//无论传得是小猫还是动物都是动物在说话,这个就是静态联编
{
animal.speak();
}
4、根据程序运行的时候来选择使用(动态联编)
class Animal
{
public:
void speak()//虚函数,在函数前面加上virtual
{
cout << "动物在说话" << endl;
}
void eat()
{
cout << "动物在吃饭" << endl;
}
};
使用虚函数时,每个对象都将增大,增大量为存这个虚函数得地址得空间,就是一个指针,对于每个类,编译器都会创建一个虚函数得地址表,用前面讲的那个指针来管理,这里对面每个函数得调用就对了一步额外得操作,即到表中查找所调用得函数地址,虽然非虚函数得效率比虚函数稍高,但是不具备动态联编的功能
class Cat :public Animal
{
public:
void speak()//如果父类声明了虚函数,子类可以不用写,建议都写上
{
cout << "小猫在说话" << endl;
}
virtual void eat()
{
cout << "小猫在吃鱼" << endl;
}
};
void doSpeak(Animal & animal) //这里传动物就是动物说话,传小猫就是小猫说话
{
animal.speak();
}
在这个函数其实就会发生多态,父类指针或引用指向子类对象,如果传的时子类,小猫那么就是父类引用指向子类对象,这个指向的是谁,就是调用的谁的虚函数的。这里重父类继承过来的虚函数一般会重写,不重写没有意义
如果发生了继承关系,编译器允许进行类型转换,这里的类型转换是父类转子类是安全的,因为,子类继承父类,子类继承了父类成员,子类有父类的成员,所以安全,但是子类转父类,不安全,因为父类不一定有子类的成员所以不安全。
二、虚析构和纯虚析构
一个类中如果有了纯虚函数或纯虚析构,那么这个类就不能用来实例化对象,但是可以定义指针
存虚函数 virtual void fun()=0;这个就是一个纯虚函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
//1、普通析构 是不会调用子类的析构的,所以可能会导致释放不干净
//利用虚析构来解决这个问题,在析构的时候回调用子类的析构
virtual ~Animal()
{
cout << "Animal的析构调用" << endl;
}
//纯虚析构 写法如下
//纯虚析构 ,需要声明 还需要实现 类内声明,类外实现
//virtual ~Animal() = 0;
//如果函数中出现了 纯虚析构函数,那么这个类也算抽象类
//抽象类 不可实例化对象
//virtual void fun() = 0;
//纯虚函数,如果出现了纯虚函数,那么这个类也是不可以示例化对象的
};
//Animal::~Animal()
//{
// //纯虚析构函数实现
// cout << "Animal的纯虚析构调用" << endl;
//}
// 如果出现纯虚析构,类也算抽象类,不能实例化对象
//void func()
//{
// Animal an;
// Animal * animal = new Animal;
//}
class Cat :public Animal
{
public:
Cat(const char * name)
{
this->m_Name = new char[strlen(name) + 1];
strcpy(this->m_Name, name);
}
virtual void speak()
{
cout << "小猫在说话" << endl;
}
~Cat()
{
cout << "Cat的析构调用" << endl;
if (this->m_Name != NULL)
{
delete[] this->m_Name;
this->m_Name = NULL;
}
}
char * m_Name;
};
void test01()
{
Animal * animal = new Cat("TOM");
animal->speak();
delete animal;
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS;
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!