媒介:
本文展示了欧洲计较机开拓商协会正在成长的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++/CLI文档包括了大量的观念变革,下文将举办表明。
二、念头
在尺度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)
}
后头的这一个例子说明白呈此刻括号内的操纵索引属性的逗号标记是表达式操纵标记,而不是一个逗号操纵符。(下面将接头这种法则带来的效果)。
(四)默认的索引属性
除了工具被编入伪域外,默认的索引属性与指定的索引属性很是相象,工具自己可以索引(似乎它自身有一个[]操纵成员函数一样),以前的代码只要稍微窜改一下就可以说明这种变革。
#p#分页标题#e#
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也将获得保存。