1.进程和线程、多态
来源:互联网 发布:逆战猎场天赋具体数据 编辑:程序博客网 时间:2024/06/05 10:03
2016.9.28 海航科技
1. 进程和线程的区别
1)l 程序是代码的集合;进程:代码的一次执行(包含多个线程)。
l 线程:进程中一个独立的单一的执行流程。
2) 进程是一个独立功能的程序,关于某个数据集合的一次运行活动状态。它可以申请和拥有系统资源,是一个活动的实体。包括程序的代码还包括当前的活动,如:程序计数器的值和处理寄存器的内容来表示。
一个进程中包含若干个线程。
3)线程和进程的区别:
l 子线程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器。多线程主要似乎为了节约CPU时间,线程运行需要使用计算机的内存资源和CPU。
l 地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程中不可见。
l 通信:多线程可共享相同的地址空间,共同分享同一个进程。
l 调度和切换:线程上下文切换比进程上下文切换要快的多。
l总结
3.区别
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
优缺点:.优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP(Symmetrical Multi-Processing,双CPU)机器上运行,而进程则可以跨机器迁移。
2.多态
同样的调用语句有多种不同的表现形式
发生的3条件:
1) 继承
2) 虚函数重写
3)父类指针(或引用)只想子类对象
//多态:同样的语句有多种不同的表现形式//根据实际对象类型决定函数调用语句#include <iostream>using namespace std;//HeroFighter AdvFighter EnergyFighterclass HeroFighter{public:virtual int power() //vitrual关键字实现多态{return 10;}};class EnergyFighter {public:int attack(){return 15;}};//::public HeroFighterclass AdvFighter:public HeroFighter{public: int power(){return 20;}};void playObj(HeroFighter *hf,EnergyFighter *ef){if (hf->power()>ef->attack())//hf->power将发生多态{cout<<"主角win\n";}else{cout<<"主角挂了\n";}}int main(){HeroFighterhf;AdvFighterAdvhf;EnergyFighter ef;playObj(&hf,&ef);playObj(&Advhf,&ef);system("pause");return 0;}int main01(){/* HeroFighterhf;AdvFighterAdvhf;EnergyFighter ef;if (hf.power()>ef.attack()){cout<<"主角win\n";}else{cout<<"主角挂了\n";}if (Advhf.power()>ef.attack()){cout<<"Adv 主角win\n";}else{cout<<"Adv 主角挂了\n";}*/system("pause");return 0;}引申实质:
C++中多态的实现原理
当类中声明虚函数时,编译器会在类中生成一个虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成与维护的
virtual成员函数会被编译器放入虚函数表中
存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr指针)
说明1:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
说明2:
出于效率考虑,没有必要将所有成员函数都声明为虚函数
5、多态原理研究(证明VPTR指针的存在)
C++编译器内部实现的时候,通过virtual关键字,内部帮我们在父类子类添加了虚函数指针和虚函数表,以下是证明虚函数指针的存在的方法
#include "iostream"
using namespace std;
class AA
{
public:
virtual void print()
{
printf("dddd\n");
}
protected:
private:
int b;
};
void main()
{
printf("AA%d \n", sizeof(AA)); //8,VPTR4字节,b字节
system("pause");
}
6、虚函数表指针(VPTR)被编译器初始化的过程
对象在创建的时,由编译器对VPTR指针进行初始化
只有当对象的构造完全结束后VPTR的指向才最终确定
父类对象的VPTR指向父类虚函数表
子类对象的VPTR指向子类虚函数表
7、为什么要定义虚析构函数
//在父类中声明虚析构函数的原因
//通过父类指针,把所有的子类析构函数都执行一遍。。。
void howtoDel(Parent *pbase)
{
delete pbase;
}
void mainobj()
{
Parent *p1 = new Parent();
p1->print();
delete p1;
}
void main()
{
Child *pc1 = new Child();
howtoDel(pc1);
//mainobj();
system("pause");
}
8、基类和子类对象指针++混搭风
class Parent01
{
protected:
int i;
int j;
public:
virtual void f()
{
cout<<"Parent01::f"<<endl;
}
};
//一次偶然的成功,比必然的失败更可怕
class Child01 : public Parent01
{
public:
int k;
public:
Child01(int i, int j)
{
printf("Child01:...do\n");
}
virtual void f()
{
printf("Child01::f()...do\n");
}
};
void howToF(Parent01 *pBase)
{
pBase->f();
}
int main()
{
int i = 0;
Parent01* p = NULL;
Child01* c = NULL;
//可以使用赋值兼容性原则,是用在多态的地方
//不要轻易通过父类指针p++,来执行函数操作
//问题的本质 子类指针 和父类指针 步长可能不一样。。。
Child01 ca[3] = {Child01(1, 2), Child01(3, 4), Child01(5, 6)};
p = ca; //第一个子类对象赋值给p,p是基类指针,
c = ca;
p->f(); //有多态发生
//c->f(); //
p++;
//c++;
p->f();//有多态发生
//c->f()
// for (i=0; i<3; i++)
// {
// howToF(&(ca[i]));
// }
system("pause");
return 0;
}
3. 面向对象
- 1.进程和线程、多态
- 第一次作业(1.线程和进程 )
- 1.Android中进程和线程
- 1.进程、线程和共享内存
- 进程和线程
- 关于进程和线程
- 进程和线程
- 进程和线程
- 小解进程和线程
- 进程和线程
- 理解进程和线程
- 进程和线程
- 进程和线程
- 进程和线程 编程
- 进程和线程
- 进程和线程
- 线程和进程
- 进程和线程编程
- oracle11.2.0.4打补丁实验
- Spring中的ContextLoaderListener使用
- 混合高斯模型GMM
- 禁止ViewPager的预加载
- strtus2中的default-action-ref无效的解决方法
- 1.进程和线程、多态
- 守护进程的创建方法和步骤
- 【碎碎念】WEB开发过程中遇到的问题或思考
- 数组合并
- 测试
- 框架-视图层
- 写代码必看!!!!
- 测试:计算员工工资
- 输出菱形