繁体   English   中英

Const引用字段作为C ++类中的readonly属性

[英]Const reference field as readonly property in C++ class

在C ++类中使用const引用字段作为只读getter是否合适?

我的意思是,这段代码是否符合良好做法?

class check{
private:
    int _x;
public:
    const int& x = _x;
    void setX(int v){
        _x = v;
    }
};

它非常像C#属性,恕我直言,并且在类使用代码中非常简单和干净:

  check s;
  int i;
  std::cin >> i;
  s.setX(i);
  std::cout << s.x << '\n';
  s.setX(7);
  // s.x = i; // Error
  std::cout<<s.x<<'\n';

这段代码符合良好做法吗?

不是真的,因为它引入了不必要的复杂性和空间开销。

此外,无论访问的值如何,您都无法执行运行时检查和/或断言。

此外,生命周期和语义会发生什么?

尝试将代码中的一个check分配给另一个,看看会发生什么。 分配不正确,因为该类是不可分配的。 您应该提供一个复制和移动构造函数来处理引用,这样它就不会引用旧对象的数据成员。

最好直接使用_x并具有简单的内联getter功能。


PS: 原生C ++中的C#属性?

一般来说,这不是一个好习惯。

imho,在课堂使用代码中非常简单和干净。

为什么要更清楚,更容易?

  • 你引入了另一个变量成员(无用的开销)。 (通常,引用将作为附加成员指针实现)。
  • 它使代码更难维护。 您实际上是在变量成员之间创建依赖关系。
  • 它在赋值和复制操作中产生问题。 如何复制操作?

“经典”的方法听起来更清晰,例如:

class Foo {
 public:
  void set_num(int value) noexcept { m_num = value; }
  int get_num() const noexcept { return m_num; }
  void set_string(std::string value) noexcept {
      m_str = std::move(value);
  }
  const std::string& get_string() const noexcept {
      return m_str;
  }
 private:
  int m_num;
  std::string m_str;
};

从性能的角度来看,这种方法应该是首选。

  • 时序复杂度: get_variable 函数上调用get_variable不会引入比“参考方法”更多的开销。 此外,它可以被编译器高度优化(因为代码简单)。
  • 空间复杂性:它不会引入额外的数据成员。

你提出的建议总的来说是一个坏主意:

  • 您无法通过任何处理来实现该属性(例如,使用[x,y]可以存储坐标的getter,然后决定将实现更改为使用[angle,radius],同时保持相同的公共接口)。
  • 使用const成员变量涉及空间开销,与内联getter相比,不会给您带来任何性能优势。
  • 这不是惯用的。
  • 一旦你发表了你的课程,而其他人开始使用它,你就会坚持下去:现在改变它以使用方法为时已晚。

如果您对属性的意图是使代码更简洁,则不必在函数名中使用“get”和“set”; 这是一种老式的做法。 您可以使用“属性”的实际名称作为函数名称,并且可以重载getter和setter:

class Cheque {
public:
    int x() const {
        return x_;
    }
    Cheque & x(int newX) {
        x_ = newX;
        return *this;
    }
private:
    int x_;
}

// Usage:
// int amt = myCheque.x(1234);
// Cheque c = Cheque().x(123);

按照上面的代码返回*this ,可以使用方法链 ; 一种实现Fluent界面习语的方法。

当C#编译一个属性时,它会被编译成一个getter和一个setter函数。

以下是一些证明这一事实的C#代码:

using System;

namespace Reflect
{
    class Program
    {
        class X
        {
            public int Prop { get; set; }
        }

        static void Main(string[] args)
        {
            var type = typeof(X);
            foreach (var method in type.GetMethods())
            {
                Console.WriteLine(method.Name);
            }
            Console.ReadKey();
        }
    }
}

你的输出应该是:

get_Prop
set_Prop
ToString
Equals
GetHashCode
GetType

get_Prop是实现getter的函数。 set_Prop是实现setter的函数。

所以,即使你所做的事情看起来很相似,也不一样。

坦率地说,几乎所有你试图在C ++中模拟“属性语法”的东西都会以这种或那种方式落空。 大多数解决方案要么花费你的内存,要么它会有一些限制,使它比有用的更麻烦。

只要学会与吸气者和二传手一起生活。 吸气剂和制定者是很好的做法 它们很短,很简单,很灵活,通常很适合内联,每个人都理解他们做的事情等等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM