Delphi和C#的类都提供了“属性”的概念,使得Getter和Setter的方法可以像访问成员一样简单,如下面的Delphi代码:
TMyClass = class
private
FValue: Integer;
funcation GetValue: Integer;
procedure SetValue(value: Integer);
public
property
Value: Integer read GetValue write SetValue;
end;
红色部分就是属性的声明,以后可以直接对Value进行读写,像下面这样:
MyClass.Value := 100;
v =
MyClass.Value;
属性有几个显而易见的好处:
- 与Getter和Setter相比更加简单,就像直接访问成员一样。
- 与直接访问成员相比,属性可以控制读写权限,并通过Getter和Setter对代码进行检验。
- 属性对UI的所见即所得编辑很有用,可以很直观的设置某个属性,如大小,颜色等;QT似乎也大量应用属性,不过我没有去看过。
C++原生没有支持属性,但这个语言的特点就是语法强大,通过一些高级属性就可以实现其他语言的特性。要实现属性,C++当然是可以胜任了,而且实现方式有很多,我在网上就看过几种实现。不过在这里我要讲另外两种实现,一种是我想到的,另一种是编译器的扩展。
先看第一种,网上通常的实现是用“模板+操作符重载”的方式,这种方式需要在类的构造函数中初始化模板类成员,并且模板类包含了3个成员:外部类指针和读写函数指针。这个模板类成员就是“属性”,一个属性将浪费掉一些存储,如果一个类存在大量属性,则这个类的空间尺寸是可观的。
我的实现是用“本地类+操作符重载”的方式,用了3种本地类,分别实现“只读,只写,可读写”三种属性,用宏包装起来方便使用,请看下面的代码:
// 取外部类实例指针(this)
//
outClass 外部类名
// localClassMem 本地类成员
#define OUTCLASS_THIS(outClass,
localClassMem) ((outClass*)((unsigned char*)this - offsetof(outClass,
localClassMem)))
// 属性定义宏
// cls
定义属性的类
// type 属性的类型
// propname 属性名
// getter 读函数
// setter
写函数
#define PROPERTY_R(cls, type, propname, getter) \
class
property_##getter \
{ \
public: \
operator type ()
\
{ \
return OUTCLASS_THIS(cls,
propname)->getter(); \
} \
} propname
#define PROPERTY_W(cls, type, propname, setter) \
class
property_##setter \
{ \
public: \
property_##setter
&operator = (const type& value) \
{ \
OUTCLASS_THIS(cls, propname)->setter(value); \
return *this;
\
} \
} propname
#define PROPERTY_RW(cls, type, propname, getter, setter) \
class property_##getter_##setter \
{ \
public: \
operator type () \
{ \
return OUTCLASS_THIS(cls,
propname)->getter(); \
} \
property_##getter_##setter
&operator = (const type& value) \
{ \
OUTCLASS_THIS(cls, propname)->setter(value); \
return *this;
\
} \
} propname
有了这几个宏,就可以写一个测试类来看看结果了:
class Test
{
public:
PROPERTY_R(Test, int,
ValueR, GetValueR);
PROPERTY_W(Test, float, ValueW, SetValueW);
PROPERTY_RW(Test, bool,
ValueRW, GetValueRW, SetValueRW);
Test():
mValueR(100), mValueW(0),
mValueRW(false)
{
}
int GetValueR()
{
return mValueR;
}
void SetValueW(const float
value)
{
mValueW =
value;
}
bool
GetValueRW()
{
return
mValueRW;
}
void
SetValueRW(bool
value)
{
mValueRW =
value;
}
private:
int
mValueR;
float mValueW;
bool mValueRW;
};
int _tmain(int
argc, _TCHAR* argv[])
{
Test
test;
int v = test.ValueR;
cout<<v<<endl;
test.ValueW = 1.0f;
test.ValueRW
= true;
cout<<test.ValueRW<<endl;
return 0;
}
基本上可以满足要求了,内部类没有成员,一个类只占一个字节,比之前面的要节省得多。
尽管用标准语法可以实现“属性”,但仍有一些不足之处,首先是属性若传入有可变参数的函数时会有问题,如下面:
printf("%d",
test.ValueR);
编译器识别不出可变参数的具体类型,因此ValueR并没有默认转换为int,要这样写才正确:
printf("%d",
(int)test.ValueR);
另外一个问题是“数组属性”如何实现,至少我没有找到更好的办法,若哪位朋友有好的办法,不访分享出来。
如果你确定你的代码只会运行在Windows上,并且只用VC作为编译器,那么就可以用第二种实现。微软提供了property关键字用来支持属性机制,编译器会自动将属性替换为Get或Set函数,这样一来属性就根本不占用任何空间,也没有任何调用开销。
下面同样包装了几个宏,不仅实现了普通属性,也实现了数组类型的属性:
#define PROPERTY_R(type, propname, getter)
__declspec(property(get=getter)) type
propname
#define PROPERTY_W(type, propname, setter)
__declspec(property(put=setter)) type
propname
#define PROPERTY_RW(type, propname, getter, setter)
__declspec(property(get=getter, put=setter)) type propname
#define PROPERTY_ARRAY_R(type, propname, getter)
__declspec(property(get=getter)) type
propname[]
#define PROPERTY_ARRAY_W(type, propname, getter)
__declspec(property(put=setter)) type
propname[]
#define PROPERTY_ARRAY_RW(type, propname, getter, setter)
__declspec(property(get=getter, put=setter)) type propname[]
有了编译器的支持,事情的确简单得多了。
分享到:
相关推荐
本项目“C++实现属性表单和向导生成”聚焦于如何利用C++来构建用户界面(UI),特别是属性表单和向导,这对于创建用户友好的应用程序至关重要。 属性表单通常用于设置或修改对象的属性。它们展示一系列的控件,如...
在C++中实现Canny算子通常涉及到以下几个关键步骤: 1. **噪声过滤**:首先,使用高斯滤波器来平滑图像,以减少噪声对边缘检测的影响。高斯滤波器的核大小和标准差可以根据实际图像的噪声水平来选择。 2. **计算...
在C++实现中,我们可以使用如 `std::vector` 和 `std::unordered_set` 这样的容器来存储和操作数据点。`std::vector` 可用于存储数据点集合,`std::unordered_set` 可用于快速查找邻域点。计算邻域通常可以通过空间...
在C++实现中,通常会包含以下四个类: 1. **DataSet类**:这是整个系统的基础,用于存储原始数据。它通常包含数据实例的集合以及每个实例的属性值。这个类需要提供添加、删除和访问数据实例的方法,以及获取属性...
C++实现数据库DBMS建表插入删除属性功能
本项目"用C++实现小人跳舞"正是这样一种实践,它利用C++语言的基本控制结构和输出功能,构建了一个简单的字符动画,模拟小人跳舞的情景。 首先,我们要理解C++语言的基础知识。C++是静态类型的、编译式的、通用的、...
在C++编程语言中,高级属性是提升代码效率和可维护性的关键要素。这个资源集合涵盖了C++的一些核心概念,包括模板、继承、多态、动态内存管理以及类的高级特性。下面将对这些主题进行深入讲解。 1. **C++模板**:...
在本项目中,标题"用C++实现的简单sql数据库"揭示了我们正在讨论一个使用C++编程语言构建的轻量级SQL数据库管理系统(DBMS)。C++是一种强大的、通用的编程语言,以其效率和灵活性著称,因此是实现数据库系统底层...
综上所述,"C++实现电梯调度模拟"项目涵盖了算法设计、数据结构应用、面向对象编程和系统优化等多个IT领域的知识点。通过这个项目,不仅可以提升编程技能,还能对实际生活中的问题有更深入的理解。
总的来说,用Visual C++实现扫雷程序是一个综合性的项目,涉及到C++语言基础、MFC框架、控件操作、事件处理、随机数生成、数据结构、算法以及图形界面设计等多个方面的知识。通过这个项目,开发者不仅可以提升编程...
通过上述方法,我们可以在C++中实现对文件属性和时间戳的修改。这对于文件管理系统、日志记录或者任何需要控制文件状态的应用场景都十分有用。在实际开发中,应确保遵循安全编程原则,避免因误操作导致的数据丢失或...
在本项目中,"CAN_BUS c++实现 源代码"提供了用C++编程语言实现CAN总线功能的示例代码,这对于理解和学习CAN总线通信机制以及C++编程技巧非常有帮助。 在C++中实现CAN总线通信,通常需要使用特定的硬件接口,如CAN...
下面我们将详细探讨这个C++实现的五子棋游戏涉及的知识点。 1. **C++基础语法**:项目的实现基于C++语言,因此首先需要了解C++的基本语法,包括变量声明、数据类型、流程控制语句(如if、for、while)、函数定义与...
在本项目中,“驾驶证管理C++实现”是一个利用C++编程语言设计的系统,用于管理和操作驾驶员的相关信息。这个系统可能包含了对驾驶证的增删改查等基本功能,旨在提高驾驶证信息管理的效率和准确性。下面我们将深入...
在C++中实现蓝牙通讯,我们需要理解这些层的工作原理,并能够用C++语言来模拟它们的功能。 1. **物理层**:这是蓝牙通信的底层,定义了无线射频(RF)规范,如频率分段、调制方式和功率控制。在C++中,我们可能需要...
《图书管理系统C++实现》是一个非常适合C++初学者学习的项目,它涵盖了基础的面向对象编程概念和实际应用。下面将详细阐述这个系统的实现细节及其涉及的C++知识点。 首先,我们从`main.cpp`开始,这是程序的入口点...
本项目"用户权限管理模块(C++实现)"是一个用C++编程语言实现的权限管理解决方案,它包含了几个核心功能,如单例模式、用户区分、用户管理以及密码安全存储。 首先,我们来深入理解C++实现的用户权限管理模块。C++...
在Qt框架中,QML(Qt Meta Language)和C++是两种主要的编程语言,它们在构建用户界面和实现业务逻辑方面各自发挥着重要作用。QML以其声明式语法和直观的UI设计,使得构建现代、动态的应用变得简单,而C++则提供了...
在C++编程中,属性对话框模板是一种常用的技术,它允许开发者创建用户界面,这些界面可以方便地编辑和查看对象的属性。属性对话框通常由一系列控件组成,如文本框、复选框和组合框,用于显示和修改对象的各种特性。...