虚函数
简单地说,那些被virtual关键字修饰的类中的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。
指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
#include <stdio.h>
struct A{
void print_1(){printf("A_1\n");}
virtual void print_2(){printf("A_2\n");}
};
struct B:A{
void print_1(){printf("B_1\n");}
void print_2(){printf("B_2\n");}
};
int main()
{
A *p1=new B;//1.此处是通过基类类型的引用或指针进行函数调用的
B *p2=new B;
p1->print_1();
p1->print_2();//2.虚函数的存在
p2->print_1();
p2->print_2();
}
输出结果为:
A_1
B_2
B_1
B_2
c++中的函数调用默认是静态绑定的,如果要触发动态绑定,要满足两个条件,就是如上程序中的注释。
如果没有virtual修饰,指向基类A的指针不知道所绑定的对象的类型,无论是引用基类还是派生类的,编译器都会当做基类对象,因为当做基类对象是安全的。这是编译器的特性。
动态绑定、静态绑定
静态绑定是指在程序编译过程中,把函数(方法或者过程)调用与响应调用所需的代码结合的过程称之为静态绑定。
除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问. 函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。在计算机语言中有两种主要的绑定方式,静态绑定和动态绑定.。
静态绑定,也叫早绑定,发生于数据结构和数据结构间,程序执行之前. 静态绑定发生于编译期, 因此不能利用任何运行期的信息. 它针对函数调用与函数的主体,或变量与内存中的区块.
动态绑定则针对运行期产生的访问请求,只用到运行期的可用信息. 动态绑定发生于运行期 在面向对象的代码中,动态绑定意味着决定哪个方法被调用或哪个属性被访问,将基于这个类本身而不基于访问范围.
所以在这样的题目里:
#include<iostream>
using namespace std;
class A{
public:
void test()
{ printf("test A"); }
};
int main(){
A* pA = NULL;
pA->test();
return 0;
}
pA指针虽然指向的是空,但是对于非虚成员函数,C++这门语言是静态绑定的。这也是C++语言和其它语言Java, Python的一个显著区别。所以test函数作为非虚函数,在编译时就确定了。即使pA为null,但是已经声明了类型,就知道pA有个test函数,且test函数里没有用到成员变量,单单一个打印语句是可以运行成功的。
const
遇到const修饰的时候,从右向左读 最容易区分
如:
const int *p1;//const 修饰的是int *p1 ,也就是变量 *p1,说明变量*p1的值不能改变,就是p1所指向的变量是常量变量
int const *p2 = &i; //const修饰的是 *p2,说明变量*p2的值不能改变,也就是p2指向常量变量
int *const p3 = &i; //const修饰的是 p3 说明指针变量p3的值不能改变,也就是不能让p3指针再指向其他地址。