第一次讲课

 今天给团队的新成员上了一下面向对象思想的课,贴一下课件(可能有一些语法上的错误,请见谅)。

封装

我们以square代表正方形这种类,正方形有color,正方形可以display。这里color就是成员变量,display是成员变量。

这个类我们可以这么写:

class           CSquare

{

  private:

int m_color;

  public:

         void display(){…}

         void setcolor(int color){ m_color = color}

void getcolor(){return m_color}

}

Csquare square = new Csquare();

square.m_color=blue;

square.display();

成员变量可以只在类内部处理,也可以开放给外部处理。以数据封装的的目的而言,前者较为妥当。

把数据声明为private,不允许外界随意存取,只通过特定接口来操作,这就是封装。

继承

考虑以下几个类

class  CShape //形状

{

 private:

         int m_color;

 public:

         void setcolor(int color){ m_color = color}

};

 

class CRect : public CShape //矩形是一种形状

{

 public:

   void display(){…}

};

 

class CEllipse:public CShape //椭圆是一种形状

{

 public:

   void display(){…}

};

 

class CTriangle:public CShape //三角形是一种形状

{

 public:

   void display(){…}

};

this指针

事实:

现在有两个CRect的实例对象rect1 , rect2他们有各自的m_color,但他们共享父类CRect::setcolor(其实是CShape::setcolor).

也就是说:

         rect1.setcolor(color)  调用的是 CRect::setcolor(color)

rect2.setcolor(color)  调用的是 CRect::setcolor(color)

问题来了:

         同一个setcolor他怎么知道要把color赋值给rect1m_color还是rect2m_color

真相:

         调用的是CRect::setcolor(int color,CRect*  this){  this.m_color = color  }     

多态

问题:

         以上三个类都有display方法,可不可以提升到CShape上去,然后再继承?

答案:能?不能?

需求:

         我们想用一个循环进行形状打印

         Cshape shape=new Cshape();

         Crect rect;

         rect = shape;//对不对?

         CShape shapes[3];

         shapes[0]  = new CRect();//为什么可以这样赋值?

         shapes[1]  = new CTriangle ();

shapes[2]  = new CEllipse();

         for (int i=0; i<3;i++)

{

         shapes[i].display();//会不会报错?

}

思考:以上所做的工作能实现这个需求吗,打印出来是想要的结果吗?

怎么实现?

    virtual(虚函数)

         改写CShape类:

class  CShape //形状

{

 private:

         int m_color;

 public:

         void setcolor(int color){ m_color = color}

         virtual void display(){}

                   virtual void test(){}//纯粹为了说明虚函数而加上去的

                  

};

         对象实例内存形态:

                                 vtable

vptr

---------à

(*display)()

------------à

CShape::display()

m_color

 

(*test)()

------------à

CShape::test()

                 

         改写CRect类:

         class CRect : public CShape //矩形是一种形状

{

 public:

   virtual void display(){打印矩形}

};

 

vptr

---------à

(*display)()

------------à

CRect::display()

m_color

 

(*test)()

------------à

CShape::test()

 

1、当调用一个对象的函数时,系统会直接去检查这个对象声明定义的类,即声明类,看所调用的函数是否为虚函数;

 

2、如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。

 

3、在这个实例类里,他会检查这个实例类的定义中是否有重新实现该虚函数(通过override关键字),如果是有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的函数。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。

using System;

 

namespace Zhisi.Net

{

    class A

    {

        public virtual void Func() // 注意virtual,表明这是一个虚拟函数

        {

            Console.WriteLine("Func In A");

        }

    }

 

    class B : A // 注意B是从A类继承,所以A是父类,B是子类

    {

        public override void Func() // 注意override ,表明重新实现了虚函数

        {

            Console.WriteLine("Func In B");

        }

    }

 

    class C : B // 注意C是从A类继承,所以B是父类,C是子类

    {

    }

 

    class D : A // 注意B是从A类继承,所以A是父类,D是子类

    {

        public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是实现

        {

            Console.WriteLine("Func In B");

        }

    }

 

    class program

    {

        static void Main()

        {

            A a;         // 定义一个a这个A类的对象.这个A就是a的声明类

            A b;         // 定义一个b这个A类的对象.这个A就是b的声明类

            A c;         // 定义一个c这个A类的对象.这个A就是b的声明类

            A d;         // 定义一个d这个A类的对象.这个A就是b的声明类

 

            a = new A(); // 实例化a对象,Aa的实例类

            b = new B(); // 实例化b对象,Bb的实例类

            c = new C(); // 实例化b对象,Cb的实例类

            d = new D(); // 实例化b对象,Db的实例类

 

            a.Func();    // 执行a.Func1.先检查声明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A

            b.Func();    // 执行b.Func1.先检查声明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B

            c.Func();    // 执行c.Func1.先检查声明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B

            d.Func();    // 执行d.Func1.先检查声明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A

            D d1 = new D();

            d1.Func(); // 执行D类里的Func(),输出结果 Func In D

            Console.ReadLine();

        }

    }

}

委托

            this.button_daoshu.Click += new System.EventHandler(this.fuhao_Click);

            private void fuhao_Click(object sender, EventArgs e)

 

概念:

         什么是委托:

1.       类型安全的函数指针

2.       方法特征的一个名称

         什么是事件:

1.       widows消息的封装

2.       委托的一种特殊形式

public delegate void CatShoutEventHandler();

pubic event CatShoutEventHandler CatShout;

 

class cat

{

         private  string name;

         public Cat(string name)

{

         this.name = name;

}

public delegate void CatShoutEventHandler();

public event CatShoutEventhandler CatShout;

public void Shout()

{

         console.writeline(“喵,我是{0}.”,name);

         if(CatShout != null)

{

         CatShout();//注意无参数无返回值

}

}

 

class Mouse

{

         private string name;

         public Mouse(string name)

{

         this.name = name;

}

public void Run()

{

         console.writeline(“老猫来了,{0}快跑!name);

}

}

 

static void Main(String[] args)

{

         Cat cat = new Cat(“Tom”);

         Mouse mouse1=new Mouse(“Jerry”);

         Mouse mouse2=new Mouse(“Jack”);

        

//多播委托

         cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run);

         cat.CatShout += new Cat.CatShoutEventHandler(mouse2.Run);

        

         cat.Shout();

         Console.Read();

}

输出结果:

喵,我是Tom

老猫来了,Jerry快跑!

老猫来了,Jack快跑!

 

问题:

private void button1_Click(object sender,EventArgs e)

{

    

}

sender是什么?e又是什么?

 

添加如下类:

public class CatShoutEventArgs:EventArgs

{

         private string name;

         public string name

         {

                   get{return name;}

                   set{name = value}

         }

}

 

改写cat

class cat

{

         private  string name;

         public Cat(string name)

{

         this.name = name;

}

public delegate void CatShoutEventHandler(object sender, CatShoutEventArgs args);

public event CatShoutEventhandler CatShout;

public void Shout()

{

         console.writeline(“喵,我是{0}.”,name);

         if(CatShout != null)

{

         CatShoutEventArgs e = new CatShoutEventArgs();

         e.Name = this.name;

         CatShout(this , e);//必须有参数

}

}

改写Mouse

class Mouse

{

         private string name;

         public Mouse(string name)

{

         this.name = name;

}

public void Run(object sender, CatShoutEventArgs args)

{

         console.writeline(“老猫{0}来了,{1}快跑!args.Name, name);

}

}

Main函数不变

输出结果:

喵,我是Tom

老猫Tom来了,Jerry快跑!

老猫Tom来了,Jack快跑!

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值