动态联编 和 静态联编 :
联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不同,可分为静态联编和动态联编; 就是说 是一个不同阶段(编译、运行)找对象的过程。
另外,为什么会产生这些问题?
感觉是为了 用不变的代码,实现可变的算法。 说实话,这句话 啥意思
为什么要找对象:因为有继承 有重写(覆盖),继承出来的对象、或者基对象 调用同一个名字的方法时,确定调用哪个类中的方法 应该遵循什么规则?
上代码吧 :静态联编 :
[cpp] view plain copy print?
#include <iostream>
using namespace std;
class shape{
public:
void draw(){cout<<"I am shape"<<endl;}//
void fun(){draw();}
};
class circle:public shape{
public:
void draw(){cout<<"I am circle"<<endl;}
};
void main(){
circle oneshape;
oneshape.fun();
}
I am shape
#include"iostream.h"
class A
{public:
voidf(){cout<<"A"<<"";}
};
classB:publicA
{public:
voidf(){cout<<"B"<<endl;}
};
Void main()
{A*pa=NULL;
Aa;Bb;
pa=&a;pa->f();
pa=&b;pa->f();
}
该程序的运行结果为:A A
动态联编
[cpp] view plain copy print?
#include <iostream>
using namespace std;
class shape{
public:
void virtual draw(){cout<<"I am shape"<<endl;}//这里设定了draw是虚函数
void fun(){draw();}
};
class circle:public shape{
public:
void draw(){cout<<"I am circle"<<endl;}//虽然没有说明circle类中的draw是虚函数,但是circle其实继承了virtual性质
};
void main(){
circle oneshape;
oneshape.fun();
}
I am circle
#include"iostream.h"
classA
{public:
Virtual voidf()//虚函数
{cout<<"A"<<"";}};
classB:publicA
{public:
Virtual voidf()//虚函数
{cout<<"B"<<endl;}
};
voidmain()
{ A*pa=NULL;
Aa;Bb;
pa=&a;
pa->f();
pa=&b;
pa->f();
}
该程序的运行结果为:A B
动态联编 和 静态联编 的功能:实现了多态性。
关于面向对象的三个基本要素:封装(类型抽象), 继承 和 多态。
实现动态联编需要同时满足以下三个条件:
① 必须把动态联编的行为定义为类的虚函数。
② 类之间应满足子类型关系,通常表现为一个类从另一个类公有派生而来。
③ 必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。
为什么加入虚函数就会不一样呢,就实现了动态联编呢?
自己的理解,不知道对不对:调用方法时,会找到某一个地址,然后执行这一段代码。加入虚函数的时候,类中会加入一张表,这个表中就像一个地图,告诉你该找到那个地址。
在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。所以c++才搞了个虚函数。其实虚函数的本质就是搞了个数据结构。也就是虚函数表
关于虚函数这个事情 可以看:看http://blog.csdn.net/haoel/article/details/1948051/
动态编联,其实就是想弄出个数据结构来,这个数据结构用来存放 映射关系,也就是联编。所以函数中只存在虚函数的时候,占用内存是4…好像是 。如果存在两个虚函数呢?
还有个问题:为什么要用基类指针指向派生类对象?
答案肯定是为了多态 为了动态联编 ,动态联编的第三个条件嘛,但是为什么。。。。为什么。。。
多态:即向不同的对象发送同一个消息,不同的对象在接受时会产生不同的行为。
我们可以理解为,继承同一基类的不同派生对象,对来自基类的同一消息执行了不同的行为,这就是多态,它是通过继承和虚函数实现的。而接受同一消息的实现就是基于基类指针。
#include <iostream>
using namespace std;
class Shape
{
public:
virtual double area() const = 0; //纯虚函数
};
class Square : public Shape
{
double size;
public:
{
size = s;
}
virtual double area() const
{
return size * size;
}
};
class Circle : public Shape
{
double radius;
public:
Circle(double r)
{
radius = r;
}
virtual double area() const
{
return 3.14159 * radius * radius;
}
};
int main()
{
Shape* array[2]; //定义基类指针数组
Square Sq(2.0);
Circle Cir(1.0);
array[0] = &Sq;
array[1] =&Cir;
for (int i = 0; i < 2; i++) /
{
cout << array[i]->area() << endl;
}
return 0;
}
再来理解一下 泛型技术:所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。
游戏里面,A人物出拳,B人物出拳。写了一段代码,实现两个人的出拳动作。为了方便后期更改,都会 用到虚函数
那么重载是不是联编吗?
重载是。。。多态吗?
要有重写,要有继承,父类指向子类 (java编程思想) 所以。。不是