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.多态

引用自:http://blog.csdn.net/wu5215080/article/details/39125039

 同样的调用语句有多种不同的表现形式

发生的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));    //8VPTR4字节,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; //第一个子类对象赋值给pp是基类指针,

         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. 面向对象


 

0 0
原创粉丝点击