侧边栏壁纸
  • 累计撰写 185 篇文章
  • 累计创建 77 个标签
  • 累计收到 17 条评论

目 录CONTENT

文章目录

C++如何实现类似C#中的属性(Property)

码峰
2023-09-24 / 0 评论 / 0 点赞 / 974 阅读 / 928 字 / 正在检测是否收录...
广告 广告

前言

在C#中,属性(Property)是比较常用的,也是非常有用的特性,通过属性,可以比较方便的在对类的一些成员变量赋值或取值的时候执行一些代码,以达到赋值或取值的时候做出特定的动作。而在C++中,类就只有成员变量和成员函数,没有类似C#中的属性的用法。

C++如何实现属性

定义属性类

C++可以通过自定义类的方式来实现类似属性的功能,先定义一个Property模板类,代码如下:

#include <functional>

template<class T>
class Property
{
    std::function<T (void)> _get;
    std::function<void(const T&)> _set;
public:
    Property(
        std::function<T (void)> get,
        std::function<void(const T&)> set)
        : _get(get),
          _set(set)
    { }

    Property(
        std::function<T(void)> get)
        : _get(get),
          _set([](const unsigned int&){})
    { }

    operator T () const { return _get(); }
    void operator = (const T& t) { _set(t); }
};

使用属性类

在Test类中使用以上定义的属性类来实现属性:

class Test
{
private:
    std::string  _label;

public:
    Property<std::string> Label = Property<std::string>
    (
        [this]()->std::string
        {
            return this->_label;
        },
        [this](const std::string& value)
        {
            this->_label = value;
        }
    );
    Property<unsigned int> LabelSize = Property<unsigned int>
    (
        [this]()->unsigned int
        {
            return this->_label.size();
        }
    );
};

在Test类中,我们定义了Label和LabelSize两个Property类型的成员变量,其中Label初始化的构造函数,传入了get和set对应的lambda表达式作为get和set执行时执行的代码,LabelSize初始化的构造函数只包含了get执行的代码,是一个只读的属性。

测试代码如下:

Test test;
test.Label = "std functional";

std::cout << "label      = " << std::string(test.Label) << std::endl
          << "label size = " << int(test.LabelSize) << std::endl;

在测试代码中,我们申明了一个Test类型的变量test,给Label赋值,可以直接像赋值字符串一样把一个常量或string类型的字符串赋值给它,而Label是只读属性,可以直接通过强制类型转换为int。同时,也可以直接谈LabelSize赋值给一个int的变量,并且不需要写强制类型转换的代码。以上测试代码的运行结果如下:

label      = std functional
label size = 14

C++属性的优缺点

我们通过自定义一个Property类,然后通过lambda表达式的方式,实现类似C#中get和set时执行相应的代码,这种方式有优点也有缺点。
主要优点:

  • 能实现类似C#的属性的功能
  • 通过lambda表达式实现get和set的执行代码,使用简单
  • 用法上也比较直观,可以直接转换为模板中的模板类型变量,也可以反过来转换

主要缺点:

  • 不能完全像C#使用那么灵活
  • 在表达式中如果没有明显的类型推导,需要写强制类型转换
  • 如果模板类中是一个类,无法直接通过“.”或“->”访问到类的成员,需要先转换为对应类型的变量才能访问,这对于连续多级属性使用上不方便

总之,这也是一种习惯于C#的属性的用户来说,在C++中也是一种行之有效个替代方法,可以根据自己的程序代码的要求进行取舍,在C++中规范的做法还是用成员函数"getXXXX"和“setXXXX”来实现属性的访问。

0
广告 广告

评论区