首页 > 解决方案 > 没有标准构造函数的类的 C++ 属性模板

问题描述

我想实现一个完全不使用 C 宏的 C# 属性的 C++ 等价物。get()我创建了一个模板,它基本上以一种比set(). 在构造函数中还有两个类型的参数std::function,我可以在其中覆盖默认的 getter 和 setter 方法。

template<typename T>
class Property
{
public:

  Property(T initialValue, std::function<void(T&)> setter, std::function<T&()> getter)
  {
    Value = initialValue;
    Setter = setter;
    Getter = getter;
  }

  ~Property()
  {
  }

  void operator =(T value)
  {
    if(Setter == nullptr)
    {
      Set(value);
    }
    else
    {
      Setter(value);
    }
  }

  T& operator ()()
  {
    if(Getter == nullptr)
    {
      return Get();
    }
    else
    {
      return Getter();
    }
  }

  void Set(T& value)
  {
    Value = value;
  }

  T& Get()
  {
    return Value;
  }

private:

  T Value;

  std::function<void(T&)> Setter = nullptr;
  std::function<T&()> Getter = nullptr;

}

以下代码片段显示了Property类型对象的定义int。(getter 和 setter 被 lambda 表达式覆盖。)

Property<int> prop = Property<int>(0,

  [&](int& val)
  {
    // some code inside the overridden setter

    prop.Set(val);
  },

  [&]() -> int&
  {
    // some code inside the overridden getter

    return prop.Get();
  });

Getter 和 setter 的调用方式如下:

int foo = prop();

prop = foo;

我以为一切都会好起来的,而且确实如此。在我尝试将一个不包含标准构造函数的类作为模板类型传递之前,它确实如此。我知道,声明T Value;会导致问题,但我无法找出任何替代方案或解决方法。

也许,您知道如何在没有标准构造函数的情况下使这个概念适用于原始类型、类和类。

标签: c++classtemplatesconstructorproperties

解决方案


IMO,这门课是个坏主意。

所有这些std::functions 可能会增加合理的开销(在性能和内存方面)。


也就是说,这是答案:

Value在构造函数的成员初始化列表中指定默认初始化(然后分配值)的Property原因。Value

解决方案是在成员初始化器列表中对其进行初始化,而不是在构造函数主体中分配给它:

Property(T initialValue, std::function<void(T&)> setter, std::function<T&()> getter)
    : Value(initialValue)
{
    Setter = setter;
    Getter = getter;
}

Setter为and做同样的事情是个好主意Getter


此外,Get并且operator()不得返回非const引用(按值或按const引用返回)。在此处返回非常量引用允许用户绕过指定的设置器并直接更改值。此外,您应该制作Getoperator() const

operator=, Set, 并且std::function<...> Setter应该通过const引用获取新值。

您应该将对的引用和对它的引用作为参数传递T ValueSetterconst不是Getter在 lambda 中捕获对属性的引用。如果引用被移动,捕获引用会使您的课程中断。

Getter应该按值返回(以允许它返回修改后的Value),或返回void(如果它的唯一目的是在返回值时调用函数,而不能修改返回的内容)。


推荐阅读