【问题标题】:What is the C++ equivalent of C#'s readonly field modifier? [duplicate]C# 的 readonly 字段修饰符的 C++ 等价物是什么? [复制]
【发布时间】:2011-08-26 14:29:48
【问题描述】:

锁定状态很棒。在 C# 中,您可以通过将字段声明为 readonly 来确保字段在构造函数完成后不会更改其值/引用。

class Foo
{
    private readonly string _foo;

    public Foo() {
        _foo = "Unchangeable";
    }

    public void ChangeIt() {
        _foo = "Darn";        // compiler error
    }
}

我可以用 C++ 做同样的事情吗?如果是这样,怎么做?如果没有,为什么不呢?

【问题讨论】:

  • @NicolBolas 你把它当作一个骗子关闭了,但它排在第一位,并且浏览量是原版的四倍。
  • 目标问题有更好的答案。这更重要。这里接受的答案是一个仅链接的答案,它提到了一个关键字,就好像这解释了一切。那里接受的答案详细介绍了const 是什么以及如何使用它。

标签: c++ field immutability readonly


【解决方案1】:

C++ 中的引用不可重新绑定,因此它等同于 C# 只读引用。

【讨论】:

  • 无法更改引用。但是,可以更改参考指向的事物。成员std::string &s 可以很好地更改,并且更改会传播给使用它的每个人。
  • @delnan:C# 的 readonly 工作方式相同,只读 StringBuilder 可以更改其内容,但不能绑定到不同的 StringBuilder。
  • 不,不是。可以更改引用以引用完全不同的对象,而只读字段始终引用同一事物,即使该事物可能会更改其内部状态。对于引用类型,它在实践中可能足够相似。但是值类型的区别是显而易见的,值类型可以通过 C++ 引用进行更改,但不能通过 C# 只读字段进行更改。
  • 值类型的 C# 只读与引用类型完全不同。 C++ 引用一旦绑定就不能指向不同的对象,但是在 C++ 中改变 int 的值并不会指向不同的对象。
  • 重点是:x = 0; 不应该工作。使用 C++ 引用,它确实如此。对于 C# 只读字段,它不会。 (但对于 nitpick,除非您考虑位置 - 例如变量 - 引用指的是“对象”,否则您仍然是错误的,这可能是有效的,但没有用,并且超出了“对象”在其他语言中所指的含义。)
【解决方案2】:

C++ 有const,它的作用与C# 中的readonly 相同。

const int Constant1 = 96;    
Constant1 = 200   // Compiler Error.

【讨论】:

  • 局部变量的const 是否与原始问题中的const 相同?
  • C#中的Readonly在ctr中赋值,而const是编译时已知值,所以它们不一样。
  • 常量值(在 C++ 和 C# 中)由编译器优化。 Readonly 不是因为它们的值是未知的。
  • 它的作用与 C# 中的 readonly 不同。 C++ 中的 const local 或 field 必须在定义时进行初始化。 C# 中的 Readonly 在定义时不必初始化,稍后可以在构造函数中初始化。您也可以只有只读字段而不是局部变量。此外,正如@ОгњенШобајић 所说,C# 中的 const 必须由常量表达式初始化并在编译时知道。
【解决方案3】:

那就是const。请注意,这个关键字在不同的上下文中意味着几个不同的东西。

【讨论】:

  • 两个链接都很好(前/后编辑。)非常感谢。
  • 两者描述的内容基本相同,但新版本对整个事物的负面影响要小得多。因为我喜欢 const,所以我更喜欢链接到中性描述;)如果您喜欢我的回答,也许您可​​以接受?
  • 请耐心等待我的朋友。我通常会在接受一个问题之前先搁置一段时间,看看还有什么其他答案浮出水面。一旦一个问题得到回答,它往往会减少路人的关注。享受悬念。
  • 好策略 - 从来没有想过(不需要,因为我还没有问过问题)。
  • 这个答案是错误的。 C++ 的 const 等于 C# 的 const 关键字,而不是 readonly。只有在使用初始化列表时,才能在 C++ 中的构造函数本身中为 const 字段赋值。这使得 C++ const 成员无用,因为移动和复制分配没有初始化列表之类的东西。
【解决方案4】:

没有直接这样的事情。您可以将私有字段与公共 getter(但没有 setter)一起使用。但这仅适用于调用您的代码的其他类。 Foo 始终对其成员具有完全访问权限。但既然你是Foo的实现者,这不是问题。

【讨论】:

    【解决方案5】:
    class Foo
    {
    private:
        const string _foo;
    public:
        Foo() : _foo("Unchangeable")
        {
        }
        void ChangeIt()
        {
            _foo = "Darn";        // compiler error
        }
    };
    

    【讨论】:

    • 关于以下划线开头的标识符的注释不是 100% 正确的。
    • @dalle,看来你是对的——它们只保留在全局命名空间中,而不是在类的上下文中。我会修正我的答案。 stackoverflow.com/questions/228783/…
    • +1,但很抱歉我很挑剔。
    • @dalle,无需道歉。每次我得到纠正,我都会学到一些东西,我很感激。
    【解决方案6】:

    在阅读接受的答案后,我并没有立即清楚地知道要完全等同于 readonly 关键字,您需要像这样声明成员:

    class Y
    {
    public:
         void mutate() { x = 7; } // not const member
         int x;
    };
    
    class X
    {
    private:
        Y * const member; // this only makes the pointer to Y const, 
                          // but you can still modify the object itself
    public:
        X(Y *m) : member(m) {}
    
        void f() { member->mutate(); }
    };
    

    希望这会有所帮助。

    【讨论】:

      【解决方案7】:

      在进行从 C# 到 C++ 的转录时,我的需求与您相同 这只是一个语法错误,因为这条指令存在于 C++ (visual C++)中

      语法:[只读]

      "只读 C++ 属性与只读 MIDL 属性具有相同的功能。 如果要禁止修改方法参数,请使用 in 属性。”

      来源:https://msdn.microsoft.com/en-us/library/45x4ky7s.aspx

      来源:https://msdn.microsoft.com/library/windows/desktop/aa367152

      【讨论】:

        猜你喜欢
        • 2014-05-22
        • 2014-02-06
        • 2023-03-27
        • 2015-07-10
        • 1970-01-01
        • 1970-01-01
        • 2011-12-29
        • 2021-06-15
        • 1970-01-01
        相关资源
        最近更新 更多