C++ CLI 程序编写注意事项

C++ CLI 程序编写注意事项


     最近做了一个C++ CLI的项目,感觉还是有很多注意事项的。现在写下来与大家分享,希望能对大家有所帮助。本文不会讨论更多理论上的东西,只会从实用角度出发,把相关语法内容过一遍。

1) 属性

     C++ CLI声明属性,需要使用property关键字。在属性内,需要通过get函数、set函数来设定私有的field值。

千万别忘了,在属性声明结束后要加分号。

使用C#声明属性:

 

Code
private int _age;

public Age
{
   get{return _age;}
   set
   {
     if(0>value || value>= 150)
        throw new Exception();
      _age = value;
   }
}
 

使用C++ CLI声明属性:

 

Code
private:
int _age;

public:
property int Age
{
   int get(void){return _age;};
   void set(int value)
   {
     if(0> value || value >= 150)
       throw gcnew Exception();
      _age = value;
   };
};
 

2) 方法

    当使用override关键字重载虚方法,或者使用new关键字覆盖基类方法时,关键字要写在方法名称和参数列表后面。

使用C#声明:

 

Code
public class A
{
  public int Add(int a,int b){return a + b;}
}

public class B : public A
{
  public new int Add(int a,int b){return a + b;}
}

protected override void OnPaint(PaintEventArgs pevent)
使用C++ CLI 声明:

 

Code
public ref class A
{
  public int Add(int a,int b){return a + b;}
}

public ref class B : public A
{
  public:
  int Add(int a,int b) new {return a + b;)
}

protected void OnPaint(PaintEventArgs pevent) override
3) 事件:

    这是C++CLI中比较烦人的部分,代码声明类似于属性声明。事件中的两个默认函数是add和remove。

使用C++ CLI声明事件:

 

Code
private:
 EventHandler^ _AxDownloadComplete;
public:
virtual event EventHandler^ AxDownloadComplete
{
   virtual void add(EventHandler^ value)
   {
      _AxDownloadComplete += value;
   };
   virtual void remove(EventHandler^ value)
   {
      _AxDownloadComplete -= value;
   };
};
 

4) 参数

    在C#需要传递引用,使用ref关键字。在C++ CLI中与之对应的是%,在C++ CLI中没有out关键字。

使用C#声明:

 

Code
public void GetObject(ref Object o);

使用C++ CLI声明:

 

Code
public:
GetObject(Object^ % o);
 

5) 创建对象

    在C++ CLI中可以通过new 关键字创建非托管对象。使用gcnew创建托管对象。编译器在编译时会自动检查对象的类型。

 

6) 实现接口

    在C#中,一个类无需显式的继承接口。比如:

 

Code
public interface ITest
{
  BackColor{get;set;}
}

public class MyControl : Control,ITest
{
  // 无需显式的声明BackColor属性,以为基类Control,已经含有BackColor的实现了。
}
 

    如果在C++ CLI中按照上面的类似写法,将会得到一个C3766 编译错误。编译器提示代码中未能实现ITest接口。以下的两种写法

都将会导致C3766错误:

 

Code
public interface class ITest
{
   int Add(int a,int b);
};

public ref class Impl : ITest
{

};   // error C3766


public interface class ITest
{
   int Add(int a,int b);
};

public ref class Impl : ITest
{
  public:
   int Add(int a,int b){return a + b;}
};  // error C3766
 

     大家可能会对第二种写法也会到致编译器报告C3766错误而感到诧异。其主要原因是,C++实现多态主要是通过

虚表来实现的。将需要实现多态的函数指针在运行时放入虚表中,在调用时,系统查询虚表,找到对应的指向虚函数的指针,

最后调用执行。

 

     正确的写法应该是:

 

Code
public interface class ITest
{
   int Add(int a,int b);
};

public ref class Impl : ITest
{
  public:
   virtual int Add(int a,int b){return a + b;}
};
 

     将实现方法用virtual 关键字修饰,以便编译器能够正确识别该方法为虚方法,将其指向函数的指针放入虚表内。

这就带来一个问题,如果你声明了一个根据System::Windows::Forms::Control类成员的一个接口IControl,然后声明一个类MyControl,该类继承了System::Windows::Forms::Control类和IControl接口。那么,C++编译器将不会认为MyControl类已经实现了IControl接口,而导致大量的编译错误。原因就是System::Windows::Forms::Control类的大部分方法都不是虚方法,C++编译器无法直接把基类的方法放入虚表中实现多态。因此只能自己再将Control类在封装一遍。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值