C++/CLI语言的属性探索

原创 2005年04月23日 22:49:00

本文展示了欧洲计算机开发商协会正在发展的C++/CLI(一种不同的C++语言,它方便开发人员在微软的.NET框架下更容易地开发程序)语言在C++语言上的扩展。写这篇文章的目的并不是要建议标准C++包括这部分扩展,也不是对C++/CLI的认可,而只是在探讨C++/CLI语言在这一领域的发展方向。

  一、基础知识

  C++/CLI中的属性是类似与各种数据成员(有各种操作限制)的可操作实体,但是这种操作往往被转化为调用存取函数(这主要是"getter"和"setter"函数)。例如:

struct Demo1 {
 property int Val { // 一个非常简单的整型、分级属性。
  int get() const {
   ++Demo1::access_count;
   return this->value;
 }
 void set(int v) {
  ++Demo1::access_count;
  this->value = v;
 }
}
private:
 int value;
 static unsigned long access_count;
};
int main() {
 Demo1 d;
 d.Val = 3; // 调用"set"操作函数。
 return d.Val; //调用"get"函数。
}

  存取函数的名字必须是get 或者是 set函数,两者之中的任何一个都可以被省略,但绝不能两者全省略。省略一个存取函数导致只存在一个读属性或只存在一个写属性。属性的地址是无法获取的,然而,存取函数作 为成员函数理所当然地可以被用来产生指向成员的指针常量(例如:&Demo1::Val::set)。

  属性可以使用关键字"virtual"进行声明,这意味者存取操作函数是虚函数,纯虚属性函数也是可能存在的,例如:

struct VirtualProp {
 virtual property int Val = 0 {
  int get() const; // 纯虚函数.
  virtual void set(int v); //纯虚函数,这里关键词"virtual"是多余的。
 }
 // ...
};

二、动机

  
在标准C++的上下文中,属性约定成俗地使用"get和set函数"文法,这种文法将暴露的数据和谐地转换为封闭地状态信息。在更精细的实时框架上下文中(具体的说是微软的.NET框架),属性是可以通过映射实时发觉和修改的元素。例如,现代的GUI库将它的组件参数声明为属性,可视化的界面构筑工具装载这些库,使用装载各种组件的属性列表并将结果展现到用户面前,当用户修改了一个属性,存取操作函数将被调用,例如这将触发各种GUI更新事件。

三、属性变量

  除了上述代码中声明的简单的分层属性,C++/CLI还引进了其他几种类型属性变量。

  (一)静态分层属性

  静态分层属性使用关键字"Static"来声明,它们的存取操作函数是静态的,静态属性的存取操作与静态数据成员的存取操作非常一致。(例如:使用C::P语法来获取C类的静态属性P)

  (二)不明显的分层属性

  一个属性的定义(即括号内的存取操作函数声明)可以使用分号";"来代替,在这种情况下,get和set存取函数综合成一个简单的可以存取操作的属性值。例如,C++/CLI定义的一个类如下:


struct TrivialProp {
 property int Val;
};

  上述代码从本质上与下述代码相同:

struct TrivialProp {
 property int Val {
  int get() const { return this->__Val; }
  void set(int v) { this->__Val = v; }
 }
 private:
  int __Val;
};

  (三)指定索引属性

  使用操作数组成员的老语法,指定索引可以操作一个数值集合,下面的例子显示了一维索引属性的操作。

struct Demo2 {
 property int x[std::string] {
  int get(std::string s) const { ... }
  void set(int v, std::string s) { ... }
 }
 // ...
};
int main() {
 Demo2 d;
 std::string s("CLI");
 d.x[s] = 3; // Calls Demo2::x::set(3, s)
 return d.x[s]; // Calls Demo2::x::get(s)
}

  注意,指定索引的属性不能是静态变量。

  多维的索引属性也是可以的,它引入的操作语法与C/C++中数组元素操作方法不太一样,例如:

struct Demo3 {
 property double x[std::string, int] {
  double get(std::string s, int n) const { ... }
  void set(double v, std::string s, int n) { ... }
 }
 // ...
};
int main() {
 Demo3 d;
 std::string s("CLI");
 d.x[s, 7] = 42.0; // Calls Demo3::x::set(42.0, s, 7)
 return d.x[s, 7] != 42.0; // Calls Demo3::x::get(s, 7)
}

  后面的这一个例子说明了出现在括号内的操作索引属性的逗号符号是表达式操作符号,而不是一个逗号操作符。(下面将讨论这种规则带来的后果)。

  (四)默认的索引属性

  除了对象被编入伪域外,默认的索引属性与指定的索引属性非常相象,对象本身可以索引(仿佛它自身有一个[]操作成员函数一样),以前的代码只要稍微改动一下就可以说明这种变化。

struct Demo4 {
 property double default[std::string, int] {
  double get(std::string s, int n) const { ... }
  void set(double v, std::string s, int n) { ... }
 }
 // ...
};
int main() {
 Demo4 d;
 std::string s("CLI");
 d[s, 7] = 42.0; // Calls Demo4::default::set(42.0, s, 7)
 return d[s, 7] != 42.0; // Calls Demo4::default::get(s, 7)
}

  请关注关键词"default"代替属性名的用法。

  四、一些技术性问题

  欧洲计算机制造商协会(C++/CLI标准的制订者)已经研究并解决了引入属性所带来的若干问题,下面这些内容尤其值得关注。

  (一)多维索引属性的操作

  p->x[2, 3]表达式拥有不同的意思,这要视成员x是否是属性(这种情况下逗号分隔两个索引属性)或其它成员变量(这种情况下逗号是个操作符号,表达式的意思等同于p->x[3])而定。为了在一个属性索引中获取逗号操作符的效果,开发人员可以使用圆括号(即p->x[(2, 3)])。

  (注意,在依赖模版的表达式中,这将产生模糊性,并且直到实例化时问题才能得到解决)

  (二)属性名与类型名冲突

  微软.NET框架带有很多包含属性的类(这些类最初并不是使用C++/CLI来开发的),这些包含的属性名与属性类型的名字相同,例如:

typedef int Color;
struct Conflict {
 property Color Color { // Property name hides type name
  typename Color get() const;
  void set(typename Color);
 }
 // ...
};
}

  为了帮助在这种上下文中书写代码,C++/CLI计划添加语法,使用关键词typename来标识不标准的类型(特别是"属性"),查找标志符的过程中将被忽视。上述的代码就以这种新的形式使用typename关键词。

  (三)重载的索引属性

  索引属性可以被重载,即,几个指定索引属性可以使用同一个名字共存于同一个类中,假定它们可以根据属性的类型来区分开来。相似地,默认的索引属性可以使用其他属性或操作符[]来重载。解决两意性与重载行为的规则已经被建立起来,来处理上述情况。

  (四)保留的成员名字

  C++/CLI属性通过综合特定的成员来实现,这些成员的名义由微软的.NET框架来规定,并且必须得到保留。

  如果一个类包含分层的属性或指定索引属性X,成员名 get_X 和set_X在类中得到保留(即使属性仅仅包含一个操作函数也是这样)。相似地,如果一个类包含有一个默认的索引属性,类中的成员函数get_Item 和set_Item也将得到保留。

C++/CLI学习入门(九):类的属性(转…

属性是C++/CLI的类 成员,它类似于成员变量,但实际上不是。其主要区别在于,字段名引用了某个存储单元,而属性名则是调用某个函数。属性拥有访问属性的set()...
  • dieqms
  • dieqms
  • 2014年11月13日 19:42
  • 324

[C++/CLI编程宝典][6]IL中间语言

继续上节的ildasm.exe对main.exe的IL中间语言的分析。我们知道我们在main.exe中定义了NativeClass,ValueStruct和RefClass。下面我们将做类型与IL中间...

C++/CLI:第一流的CLI语言

1. 简介   本文并不是为了奉承C++/CLI的辉煌,也不是为了贬低其它如C#或者VB.NET等语言,相反,这只是一个非官方的、以一个喜欢这种语言的非微软雇员身份来论证C++/CLI有它的自己...

钱能C++语言读书笔记(三)如何改变类成员的范围属性

钱能C++语言读书笔记(三)如何改变类成员的访问属性      在派生类中,可以调整成员的访问控制属性。例如:可以将公有成员调整为私有成员,将保护成员调整为公有成员。调整访问控制属性的前提是在派生类中...
  • ACb0y
  • ACb0y
  • 2011年02月22日 23:30
  • 671

[C++/CLI编程宝典][2]什么是C++/CLI语言

对于什么是C++/CLI,我们首先可以简单的将其名字划分为两部分来理解,第一,C++,我们熟悉的目前被广泛使用的面向对象的ISO国际标准的高级语言,也称为ISOC++,我们这里以后均称其为ISOC++...

STK X教程—C++/CLI源代码

  • 2013年03月26日 21:48
  • 134KB
  • 下载

【AngularJs】使用angular-cli实现多国语言i18n

在模板html标签中增加i18n Hello world! 使用ng命令产生xlf格式的message.xlf文件 $ ng xi18n --output-path src/i18n ...
  • hj7jay
  • hj7jay
  • 2017年04月26日 09:29
  • 301

Manning.C++CLI.in.Action.Apr.2007

  • 2013年08月30日 15:44
  • 17.83MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++/CLI语言的属性探索
举报原因:
原因补充:

(最多只允许输入30个字)