• C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅱ部分


    =================================版权声明=================================

    版权声明:本文为博主原创文章 未经许可不得转载 

    请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

    未经作者授权勿用于学术性引用。

    未经作者授权勿用于商业出版、商业印刷、商业引用以及其他商业用途。                   

    本文不定期修正完善,为保证内容正确,建议移步原文处阅读。                                                               <--------总有一天我要自己做一个模板干掉这只土豆

    本文链接:http://www.cnblogs.com/wlsandwho/p/4713311.html

    耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html

    =======================================================================

     第九章 值类型

      值类型

        C++等价形式是.net类型名称的别名,用哪个都一样。

        所有值类型都是从System::ValueType继承。

        栈上存储

        不被垃圾回收

        直接访问没差别

        值类型有必要时可以当作对象使用

      结构

        结构是值类型而非引用类型。(例如表示坐标的点)

        .net结构的优点就是可以由其他语言来使用。

        不支持继承也不能作为基类

        能实现接口

        复制结构,是拷贝。

        结构成员不可以是引用类型,引用成员必须要垃圾回收。

        可嵌套定义。

        value struct Point

        {

          int x;

          int y;

        };

        value struct Person

        {

          String^ name;

          value struct Date { int yyyy,mm,dd;};

          Date dob;

        };

      枚举

        值类型 派生自System::Enum,System::ValueType。

        栈上

        枚举成员要有类型名称限定

        Format函数  String^ s=Enum::Format(WeekDay::typeid,w,"G");

        一定要有public或private,因为C++11标准产生C2644错误。

        枚举支持任何整数类型,节省内存

          public enum class Weekday:char

    =======================================================================

    第十章 操作符重载

      操作符重载

        C++/CLI的操作符重载限制比较大,主要是因为在.net中要兼容各语言。

          遵循CLS

          gcnew和delete不恩那个重载因为内存是由.net的运行时负责的。

        Equals函数

              virtual bool Equals(Object^ other) override
              {
                  IntVal^ obj = dynamic_cast<IntVal^>(other);
                  if (obj==nullptr)
                  {
                      return false;
                  }

                  return value == obj->value;
              }

           重写Equals时也应该重写GetHashCode

        标准C++重写++时是前++和后++

        C++/CLI重写++时只有++

        转换操作符+精彩操作符

          static operator IntVal(int v)

          {

            return IntVal(v);

          }

          static IntVal operator+(IntVal liv,IntVal riv)

          {

            IntVal result(liv.value+riv.value);

            return result;

          }

     1 value struct IntVal
     2 {
     3 private:
     4     int value;
     5 public:
     6     IntVal(int v):value(v){}
     7     int getVal() { return value; }
     8     
     9 //     IntVal operator+(IntVal rhs)
    10 //     {
    11 //         IntVal result(value + rhs.value);
    12 //         return    result;
    13 //     }
    14 
    15 //     IntVal operator+(int rhs)
    16 //     {
    17 //         IntVal result(value + rhs);
    18 //         return result;
    19 //     }
    20 
    21 //     static IntVal operator+(int lhs, IntVal rhs)
    22 //     {
    23 //         IntVal result(lhs + rhs.value);
    24 //         return result;
    25 //     }
    26 
    27     static operator IntVal(int v)
    28     {
    29         return IntVal(v);
    30     }
    31 
    32     static IntVal operator+(IntVal lhs, IntVal rhs)
    33     {
    34         IntVal result(lhs.value + rhs.value);
    35 
    36         return result;
    37     }
    38 
    39     static bool operator==(IntVal lhs, IntVal rhs)
    40     {
    41         return lhs.value == rhs.value;
    42     }
    43 
    44     static bool operator!=(IntVal lhs, IntVal rhs)
    45     {
    46         return !(lhs == rhs);
    47     }
    48 
    49     virtual bool Equals(Object^ other) override
    50     {
    51         IntVal^ obj = dynamic_cast<IntVal^>(other);
    52         if (obj==nullptr)
    53         {
    54             return false;
    55         }
    56 
    57         return value == obj->value;
    58     }
    59 
    60     static IntVal operator++(IntVal i)
    61     {
    62         i.value++;
    63         return i;
    64     }
    65 };
     1 ref    struct LongVal
     2 {
     3 private:
     4     long value;
     5 public:
     6     LongVal(long v) :value(v) {}
     7     int getVal() { return value; }
     8     
     9     static operator LongVal^(long l)
    10     {
    11         return gcnew LongVal(l);
    12     }
    13 
    14     static LongVal^ operator+(LongVal^ lhs, LongVal^ rhs)
    15     {
    16         LongVal^ result = gcnew LongVal(lhs->value + rhs->value);
    17 
    18         return result;
    19     }
    20 };
     1 int main(array<System::String ^> ^args)
     2 {
     3     //Console::WriteLine(L"Hello World");
     4     IntVal one(1);
     5     IntVal two(2);
     6     IntVal three;
     7 
     8     three = one + two;
     9     Console::WriteLine(three.getVal());
    10 
    11     IntVal four;
    12     four = two + 2;
    13     Console::WriteLine(four.getVal());
    14 
    15     IntVal five;
    16     five = 3 + two;
    17     Console::WriteLine(five.getVal());
    18 
    19     IntVal somenum(2);
    20     if (somenum == 2)
    21     {
    22         Console::WriteLine(L"somenum == 2");
    23     }
    24 
    25     if (somenum != 3)
    26     {
    27         Console::WriteLine(L"somenum != 3");
    28     }
    29 
    30     IntVal six(6), seven(7);
    31     if (!six.Equals(seven))
    32     {
    33         Console::WriteLine(L"six != seven");
    34     }
    35 
    36     LongVal^ lone = gcnew LongVal(1);
    37     LongVal^ ltwo = gcnew LongVal(2);
    38     LongVal^ lthree = lone + ltwo;
    39     Console::WriteLine(lthree->getVal());
    40 
    41     return 0;
    42 }

     =======================================================================

    第十一章 异常处理

      类型转换

        safe_cast 转换失败抛出异常

        dynamic_cast转换失败返回空指针

      捕捉System::Exception派生类的对象

      C++

        构造函数 重载操作符——>异常在这些地方很有用

      C++/CLI

        传统C++异常

        C++/CLI异常

        SEH

      抛出异常

        

      形式

        try

        {

          if(a<0)

            throw gcnew ArgumentException(L"Test by WLS");

        }

        catch(ArgumentException^ ex)

        {  

          Console::WriteLine(L"Exception caught in Test by WLS");

          throw;

        }

        catch(Exception^)//捕捉所有异常 但会丢失所有异常信息

        {

        }

      创建自己的异常类型

        ref class WLSException:System::Exception

        {

          public:

            int ErrorNum;//自定义错误号

            WLSException(String^ msg,int num):Exception(msg),ErrorNum(num){}

        };

        使用时 throw gcnew WLSException(e->Message,666);

    =======================================================================

    第十二章  数组和集合

      用size_t比int要好

      泛型类型

        generic <typename T>

        ref class MyList

        {

        public:

          void Add(T num);

        }

      枚举器

        IEnumerator接口

        只能读取  修改还是要用常规循环

        迭代器模式  遍历任何集合  不保证顺序

        初始位置第一个之前

        MoveNext方法  移动到下一个元素,没有就返回false

        Current属性  当前项

        Reset方法   重置到第一个之前

      托管数组

        所有的托管数组都继承自System::Array

        array<类型,维度> handle_name

        托管堆

        垃圾回收

        索引从0开始 越界访问抛出异常

        arr1->Length  数组各维度的长度和

        arr1->GetLength(2)  第2维的长度

     1 array<Person^>^ arr3;//支持各种类型
     2 
     3 array<int>^ arr1 = { 1,2,3 };//C++风格
     4 
     5 array<int>^ arr2= gcnew array<int>(3) {4,5,6};
     6 
     7 array<int>^ arr3 = gcnew array<int>() {7,8,9};//为什么这个我的VS2015社区版不通过?  error C2748: 创建 托管 数组时必须提供数组大小或数组初始值设定项
     8 
     9 array<int, 2>^ arr1= gcnew array<int, 2>(3,3);//二维数组
    10 Console::WriteLine(arr1->Length);
    11 Console::WriteLine(arr1->GetLength(0));
    12 Console::WriteLine(arr1->GetLength(1));
    13 for (int i = 0;i < arr1->GetLength(0);i++)
    14 {
    15     for (int j = 0;j<arr1->GetLength(1);j++)
    16     {
    17         arr1[i,j] = i*j;//访问方式好独特,一个“[]”里用“,”分隔各个维度
    18     }
    19 }
    20 
    21 for (int i = 0;i < arr1->GetLength(0);i++)
    22 {
    23     for (int j = 0;j < arr1->GetLength(1);j++)
    24     {
    25         Console::WriteLine(arr1[i, j]);
    26     }
    27 }
    1 array<String^>^ arr = gcnew array<String^>(SIZE) {gcnew String(L"abc"), gcnew String(L"def")};//初始化
    2 
    3 array<String^>^ arrs = gcnew array<String^>(SIZE);
    4 arrs[0] = gcnew String(L"abc");
    5 arrs[1] = L"def";
     1 //多维数组
     2 array<int, 2>^ arr1 = { {1,2,3},{4,5,6} };
     3 for (int i = 0;i < arr1->GetLength(0);i++)
     4 {
     5     for (int j = 0;j < arr1->GetLength(1);j++)
     6     {
     7         Console::WriteLine(arr1[i, j]);
     8     }
     9 }
    10 
    11 array<int, 2>^ arr2 = gcnew array<int, 2>{ {7, 8, 9}, { 10,11,12 }};
    12 for (int i = 0;i < arr2->GetLength(0);i++)
    13 {
    14     for (int j = 0;j < arr2->GetLength(1);j++)
    15     {
    16         Console::WriteLine(arr2[i, j]);
    17     }
    18 }

     怎么在多维数组中使用foreach来遍历其中的某一维呢?

    例如遍历array<String^, 2>^ arr3 = gcnew array<String^, 2>{ {L"aa", L"bb", L"cc"}, { L"ee",L"ff",L"gg" }};的第二维的元素?

    =======================================================================

    第十三章  属性

      C++/CLI支持两种属性

        标量属性  通过取值赋值访问单个值  属性不一定是数据成员可以是导出值

        索引属性  使用[]来访问属性

      关键字 property

        构造函数里应该优先使用属性进行初始化而不是直接使用数据成员

        可以在属性里使用throw抛出异常

      自动实现属性

        property String^ Name;//默认实现get和set

      只读或只写属性

        property String^ Name

        {

          //只实现get或者set

          String^ g/set(){...}

        }

      继承、接口

        属性可以是virtual也可以是纯virtual的,可以在继承和接口中使用

     1 ref class CShape abstract
     2 {
     3 public:
     4     virtual property double    Area;
     5 };
     6 
     7 ref class CCricle:CShape
     8 {
     9 public:
    10 
    11     CCricle(double r) { m_nRadius = r; }
    12 
    13     virtual property double Area
    14     {
    15         double get() override
    16         {
    17             return Math::PI*m_nRadius*m_nRadius;
    18         }
    19     }
    20 
    21     void PrintArea()
    22     {
    23         Console::WriteLine(L"The Area is {0}",Area);
    24     }
    25 
    26 private:
    27     double m_nRadius;
    28 };
    29 
    30 
    31 
    32 int main(array<System::String ^> ^args)
    33 {
    34     CCricle^ oCricle = gcnew CCricle(4.0);
    35     oCricle->PrintArea();
    36 
    37     return 0;
    38 }

      索引属性

        默认属性

          类可以有多个索引器(索引属性),必须根据名称显示的使用。(下面的oBank->Balance[234567]

          名为default的索引属性可以在类对象上直接使用。(下面的CAccount^ pA = oBank[234567]

      1 #include "stdafx.h"
      2 
      3 using namespace System;
      4 using namespace System::Collections::Generic;
      5 
      6 //////////////////////////////////////////////////////////////////////////
      7 ref class CAccount
      8 {
      9 public:
     10     CAccount(long lAccNum,double dBalance,double dLimit);
     11     ~CAccount();
     12 
     13     property long AccountNumber
     14     {
     15         long get() { return m_lAccNumber; }
     16     }
     17 
     18     property double Balance
     19     {
     20         double get() { return m_dBalance; }
     21     }
     22 
     23     property double OverdraftLimit
     24     {
     25         double get() { return m_dLimit; }
     26         void set(double dValue)
     27         {
     28             if (dValue<0)
     29             {
     30                 throw gcnew ArgumentException(L"Limit can not be negative");
     31             }
     32 
     33             m_dLimit = dValue;
     34         }
     35     }
     36 
     37 private:
     38     long m_lAccNumber;
     39     double m_dBalance;
     40     double m_dLimit;
     41 };
     42 
     43 CAccount::CAccount(long lAccNum, double dBalance, double dLimit)
     44 {
     45     Console::WriteLine(L"Account:Constructor");
     46 
     47     if (lAccNum<0 || dLimit<0)
     48     {
     49         throw gcnew ArgumentException(L"Bad Arguments to constructor");
     50     }
     51 
     52     m_lAccNumber = lAccNum;
     53     m_dBalance = dBalance;
     54     m_dLimit = dLimit;
     55 }
     56 
     57 CAccount::~CAccount()
     58 {
     59 }
     60 //////////////////////////////////////////////////////////////////////////
     61 ref class CBank
     62 {
     63 public:
     64     CBank();
     65     ~CBank();
     66 
     67     bool AddAccount(CAccount^ oAccount)
     68     {
     69         if (m_listAccounts->Contains(oAccount))
     70         {
     71             return false;
     72         }
     73         else
     74         {
     75             m_listAccounts->Add(oAccount);
     76         }
     77 
     78         return true;
     79     }
     80 
     81     bool RemoveAccount(CAccount^ oAccount)
     82     {
     83         if (m_listAccounts->Contains(oAccount))
     84         {
     85             m_listAccounts->Remove(oAccount);
     86 
     87             return true;
     88         }
     89         
     90         return false;
     91     }
     92 
     93     property double Balance[long]
     94     {
     95         double get(long lIndex)
     96         {
     97             for each (CAccount^ var in m_listAccounts)
     98             {
     99                 if (var->AccountNumber==lIndex)
    100                 {
    101                     return var->Balance;
    102                 }
    103             }
    104 
    105             throw gcnew ArgumentOutOfRangeException(L"No Such Account");
    106         }
    107     }
    108 
    109     property CAccount^ default[long]
    110     {
    111         CAccount^ get(long lIndex)
    112         {
    113             for each (CAccount^ var in m_listAccounts)
    114             {
    115                 if (var->AccountNumber == lIndex)
    116                 {
    117                     return var;
    118                 }
    119             }
    120 
    121             throw gcnew ArgumentOutOfRangeException(L"No Such Account");
    122         }
    123     }
    124 private:
    125     List<CAccount^>^ m_listAccounts;
    126 };
    127 
    128 CBank::CBank()
    129 {
    130     Console::WriteLine(L"Bank:Constructor");
    131 
    132     m_listAccounts = gcnew List<CAccount^>();
    133 }
    134 
    135 CBank::~CBank()
    136 {
    137 }
    138 
    139 
    140 int main(array<System::String ^> ^args)
    141 {
    142     CBank^ oBank = gcnew CBank();
    143 
    144     CAccount^ oAccount1 = gcnew CAccount(123456, 10.0, 0.0);
    145     CAccount^ oAccount2 = gcnew CAccount(234567, 110.0, 10.0);
    146     CAccount^ oAccount3 = gcnew CAccount(345678, 1110.0, 110.0);
    147 
    148     oBank->AddAccount(oAccount1);
    149     oBank->AddAccount(oAccount2);
    150     oBank->AddAccount(oAccount3);
    151 
    152     CAccount^ pA = oBank[234567];
    153     Console::WriteLine(L"The Account Number {0} has the banlance {1}.", pA->AccountNumber,oBank->Balance[234567]);
    154 
    155     return 0;
    156 }

    (为什么我感觉我的代码写的有点问题,虽然可以跑?Balance属性真的这么写吗?)

    =======================================================================

    第十四章  委托和事件

       委托是特殊的类

        原理是将函数的执行委托给一个中间对象,调用具有特定签名的一个或者多个函数。

        C++/CLI的所有委托都是System::MulticastDelegate。

        关键字 delegate

          delegate double SomeOperating(double);

          只能调用托管类的成员函数(静态非静态都可以)。

            静态成员函数只需要传递函数地址

            非静态成员函数需要传递对象和函数地址

          委托创建好后不能改变调用的函数,但是可以重新gcnew一个新的,垃圾自动回收。

          调用委托可以使用invoke也可以使用委托的仿函数。

          MulticastDelegate使用Combine和Remove来操作调用列表。

          MulticastDelegate使用合并其他委托的方法来生成。

          MulticastDelegate的调用顺序由合并顺序决定。

          MulticastDelegate通常用不返回值的函数,但也可以返回值,一般是最后一个的结果。想要获得某个结果可以遍历委托列表。

     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 delegate double NumbericOp1(double);
     6 delegate double NumbericOp2(double, double);
     7 
     8 ref class Ops
     9 {
    10 public:
    11     static double Square(double dNum) { return dNum*dNum; }
    12     static double Cube(double dNum) { return dNum*dNum*dNum; }
    13     
    14     double MultiAandB(double dNum1, double dNum2) { return dNum1*dNum2; }
    15 };
    16 
    17 int main(array<System::String ^> ^args)
    18 {
    19     NumbericOp1^ NOp1 = gcnew NumbericOp1(Ops::Square);//静态函数//编译通过了
    20 
    21     double dTempNum1 = 10.0;
    22 
    23     Console::WriteLine(L"Square({0}) = {1}",dTempNum1,NOp1->Invoke(dTempNum1));
    24     Console::WriteLine(L"Square({0}) = {1}", dTempNum1, NOp1(dTempNum1));
    25 
    26     NOp1 = gcnew NumbericOp1(Ops::Cube);//静态函数//编译通过了
    27 
    28     Console::WriteLine(L"Square({0}) = {1}", dTempNum1, NOp1->Invoke(dTempNum1));
    29     Console::WriteLine(L"Square({0}) = {1}", dTempNum1, NOp1(dTempNum1));
    30 
    31     //////////////////////////////////////////////////////////////////////////
    32     double dTempNum2 = 2.0;
    33     double dTempNum3 = 3.0;
    34 
    35     Ops^ objOps=gcnew Ops();
    36 
    37     NumbericOp2^ NOp2;
    38     NOp2 = gcnew NumbericOp2(objOps, &Ops::MultiAandB);//非静态函数
    39 
    40     Console::WriteLine(L"multi({0},{1})={2}", dTempNum2,dTempNum3,NOp2->Invoke(dTempNum2,dTempNum3));
    41     Console::WriteLine(L"multi({0},{1})={2}", dTempNum2, dTempNum3, NOp2(dTempNum2, dTempNum3));
    42 
    43     return 0;
    44 }
     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 delegate void PrintSomething(int);
     6 
     7 delegate int DOperation(int);
     8 
     9 ref class CClient1
    10 {
    11 public:
    12     static void Print(int nNum) { Console::WriteLine(L"CClient1 {0}",nNum); }
    13     int DoubleNum(int nNum) { return nNum<<1; }
    14 };
    15 
    16 ref class CClient2
    17 {
    18 public:
    19     static void Print(int nNum) { Console::WriteLine(L"CClient2 {0}",nNum); }
    20     int DDoubleNum(int nNum) { return nNum << 2; }
    21 };
    22 
    23 
    24 int main(array<System::String ^> ^args)
    25 {
    26     PrintSomething^ PS1=gcnew PrintSomething(CClient1::Print);
    27     PrintSomething^ PS2=gcnew PrintSomething(CClient2::Print);
    28     PrintSomething^ PS3;
    29     PS3+= PS1+PS2;
    30     PS3(2333);
    31 
    32     Console::WriteLine(L"-------------");
    33     PS3 += PS3+PS3;
    34     PS3(233);
    35 
    36     Console::WriteLine(L"-------------");
    37     PrintSomething^ PS4;
    38     PS4 = PS3 + PS3;
    39     PS4(23333);
    40 
    41     Console::WriteLine(L"-------------");
    42     PS4 -= PS3;
    43     PS4(233333);
    44 
    45     CClient1^ oC1 = gcnew CClient1();
    46     CClient2^ oC2 = gcnew CClient2();
    47 
    48     DOperation^ DOp;
    49     DOp = gcnew DOperation(oC1, &CClient1::DoubleNum)+gcnew DOperation(oC2,&CClient2::DDoubleNum);
    50 
    51     for each (DOperation^ dop in DOp->GetInvocationList())
    52     {
    53         Console::WriteLine(dop(666));
    54     }
    55 
    56     return 0;
    57 }

       .net的事件

        发布-订阅 机制

        基于委托

          事件只能由声明它的类型引发

          客户端只能用+=和-=来增删事件处理函数,不能用=重置调用列表

        事件源声明委托

        事件接收者提供适当方法

        方法绑定到委托

        事件发生调用委托进而调用方法

     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 //////////////////////////////////////////////////////////////////////////
     6 delegate void FristEventHandler(String^);
     7 delegate void SecondEventHandle(String^);
     8 
     9 ref class EventSrc
    10 {
    11 public:
    12     event FristEventHandler^ OnFirstEvent;
    13     event SecondEventHandle^ OnSecondEvent;
    14 
    15     void RaiseOne(String^ msg) { OnFirstEvent(msg); }
    16     void RaiseTwo(String^ msg) { OnSecondEvent(msg); }
    17 };
    18 //////////////////////////////////////////////////////////////////////////
    19 ref class EventReceiver
    20 {
    21 public:
    22     EventReceiver(EventSrc^ esrc)
    23     {
    24         if (esrc==nullptr)
    25         {
    26             throw gcnew ArgumentException(L"Must have event source");
    27         }
    28 
    29         m_EventSrc = esrc;
    30 
    31         m_EventSrc->OnFirstEvent += gcnew FristEventHandler(this, &EventReceiver::DoforFirstEvent);
    32         m_EventSrc->OnSecondEvent += gcnew SecondEventHandle(this, &EventReceiver::DoforSecondEvent);
    33     }
    34 
    35     void RemoveHandler()
    36     {
    37         m_EventSrc->OnFirstEvent -= gcnew FristEventHandler(this, &EventReceiver::DoforFirstEvent);
    38     }
    39 
    40     void DoforFirstEvent(String^ msg) { Console::WriteLine(L"[Eventreceiver] event one,message {0}", msg); }
    41     void DoforSecondEvent(String^ msg) { Console::WriteLine(L"[Eventreceiver] event two,message {0}", msg); }
    42 
    43 private:
    44     EventSrc^ m_EventSrc;
    45 };
    46 
    47 int main(array<System::String ^> ^args)
    48 {
    49     EventSrc^ src = gcnew EventSrc();
    50     EventReceiver^ recvr = gcnew EventReceiver(src);
    51 
    52     src->RaiseOne(L"Hahaha");
    53     src->RaiseTwo(L"blablabla");
    54 
    55     Console::WriteLine();
    56     recvr->RemoveHandler();
    57 
    58     src->RaiseOne(L"Hahaha");
    59     src->RaiseTwo(L"blablabla");
    60 
    61     return 0;
    62 }
    63  

       标准事件 System::EventHandler

        签名  delegate void EventHandler(System::Object^ sender, System::EventArgs^ e)

        建议使用标准事件

          直接使用System::EventHandler

     1 #include "stdafx.h"
     2 
     3 using namespace System;
     4 
     5 //////////////////////////////////////////////////////////////////////////
     6 ref class CCounter
     7 {
     8 public:
     9     CCounter(int nLimit)
    10     {
    11         m_nCounter = 0;
    12         m_nLimit = nLimit;
    13     }
    14 
    15     event EventHandler^ LimitReached;
    16 
    17     void Increment()
    18     {
    19         Console::WriteLine(L"Count:{0}",++m_nCounter);
    20 
    21         if (m_nCounter % m_nLimit==0)
    22         {
    23             LimitReached(this, gcnew EventArgs());
    24         }
    25     }
    26 
    27 private:
    28     int m_nCounter;
    29     int m_nLimit;
    30 };
    31 
    32 //////////////////////////////////////////////////////////////////////////
    33 ref class CObserver
    34 {
    35 public:
    36     static void Callme(Object^ src, EventArgs^ args)
    37     {
    38         Console::WriteLine(L"Limit reached");
    39     }
    40 
    41     void CallmeBaby(Object^ src, EventArgs^ args)
    42     {
    43         Console::WriteLine(L"Oh,Honey!");
    44     }
    45 
    46 };
    47 
    48 //////////////////////////////////////////////////////////////////////////
    49 int main(array<System::String ^> ^args)
    50 {
    51     //////////////////////////////////////////////////////////////////////////
    52     CCounter^ oCounter=gcnew CCounter(5);
    53 
    54     //////////////////////////////////////////////////////////////////////////
    55     oCounter->LimitReached += gcnew EventHandler(&CObserver::Callme);
    56     
    57     for (int i = 0;i<11;i++)
    58     {
    59         oCounter->Increment();
    60     }
    61 
    62     //////////////////////////////////////////////////////////////////////////
    63     //oCounter->LimitReached -= gcnew EventHandler(&CObserver::Callme);
    64     //////////////////////////////////////////////////////////////////////////
    65     
    66     CObserver^ oObserver=gcnew CObserver();
    67 
    68     oCounter->LimitReached += gcnew EventHandler(oObserver, &CObserver::CallmeBaby);
    69 
    70     for (int i = 0;i < 11;i++)
    71     {
    72         oCounter->Increment();
    73     }
    74 
    75     return 0;
    76 }

    =======================================================================

    第十五章  .NET Framework类库

      鼓吹.NET的一章,泛泛草草的说了几页,意思大概就是之前的十四章都看完了,接着往下看吧,好戏才刚开始呢。

    =======================================================================

    第Ⅱ部分也没难度,只是容易忘、记不住。

    =======================================================================

    说说书上的错误吧

    Page75 6.5 在类中使用常量

    第一个小圆点· “它的值对于Card的所有实例来说都是4”,很显然英文拼错了,正确是“Car”


    Page174 12.3.1 初始化
    一共有三行代码,第二行的代码不能有(),应该改为array<int>^ intArray=gcnew array<int>{1,2,3};

    Page207 14.2.2 使用MulticastDelegate

    “而对于MutlcastDelegate,可使用……”中的英文显然拼错了,正确是“MulticastDelegate”

    =======================================================================

    再说说一点瑕疵

    Page195 13.2.4 属性、继承和接口

    在练习中给出的托管类定义,ref的前面是不需要public的,至少在这个例子和当前的教学上下文是不需要的。

    =======================================================================

    有空开始看第Ⅲ部分

  • 相关阅读:
    小白学 Python 爬虫(21):解析库 Beautiful Soup(上)
    小白学 Python 爬虫(20):Xpath 进阶
    小白学 Python 爬虫(19):Xpath 基操
    小白学 Python 爬虫(18):Requests 进阶操作
    Apache + WordPress 从 0 搭建
    小白学 Python 爬虫(17):Requests 基础使用
    小白学 Python 爬虫(16):urllib 实战之爬取妹子图
    小白学 Python 爬虫(15):urllib 基础使用(五)
    小白学 Python 爬虫(14):urllib 基础使用(四)
    小白学 Python 爬虫(13):urllib 基础使用(三)
  • 原文地址:https://www.cnblogs.com/wlsandwho/p/4713311.html
Copyright © 2020-2023  润新知