如何处理const对象中非常量引用成员的初始化?

2023-11-26

假设你有课

    class C 
    {
      int * i;

      public:

         C(int * v):i(v) {};

         void method() const;  //this method does not change i
         void method();        //this method changes i
    }

现在您可能想要定义此类的 const 实例

    const int * k = whatever;
    const C c1(k); //this will fail

但这会失败,因为非常量 int C 的构造函数 C(int * v)

所以你定义了一个 const int 构造函数

    C(const int * v):i(v) {}; //this will fail also

但这也会失败,因为 C 的成员“int * i”是非常量。

遇到这种情况该怎么办?使用可变的?铸件?准备类的常量版本吗?

编辑:在与帕维尔(如下)讨论后,我对这个问题进行了一些研究。对我来说,C++ 的做法是不正确的。指针目标应该是严格类型,这意味着您不能执行以下操作:

int i;
const int * ptr;
ptr = & i;

在这种情况下,语言语法对待const作为不改变指针目标的承诺。此外int * const ptr是一个不改变指针值本身的承诺。因此,有两个地方可以应用 const。那么您可能希望您的类对指针进行建模(为什么不呢)。事情正在分崩离析。 C++ 语法提供了 const 方法,这些方法能够保证不会更改字段的值本身,但没有语法指出您的方法不会更改类内指针的目标。

解决方法是定义两个类const_C and C例如。然而,这不是一条皇家道路。使用模板,它们的部分专业化很难不陷入混乱。还有所有可能的参数变化,例如const const_C & arg, const C & arg, const_C & arg, C & arg看起来不漂亮。我真的不知道该怎么办。使用单独的类或const_casts,每种方式似乎都是错误的。

在这两种情况下,我是否应该将不修改指针目标的方法标记为 const?或者只是遵循传统路径,即 const 方法不会更改对象本身的状态(const 方法不关心指针目标)。那么在我的例子中,所有方法都是 const,因为类正在建模一个指针,因此指针本身就是T * const。但显然其中一些修改了指针的目标,而另一些则没有。


听起来你想要一个可以包装的对象int*(然后表现得非常量),或者int const*(然后表现为 const)。仅靠一个类是无法真正做到这一点的。

事实上,正是这个概念const应用于你的类应该改变它的语义,就像这是错误的 - 如果你的类建模了一个指针或一个迭代器(如果它包装了一个指针,很可能是这种情况),那么const应用于它仅意味着它本身不能更改,并且不应暗示与所指向的值有关的任何内容。您应该考虑遵循 STL 对其容器所做的事情 - 这正是它具有独特之处的原因iterator and const_iterator类,两者是不同的,但前者可以隐式转换为后者。同样,在 STL 中,const iterator不等于const_iterator!所以就做同样的事情吧。

[EDIT]这是一种最大限度地重用代码之间的棘手方法C and const_C同时确保自始至终的常量正确性,而不是深入研究 U.B. (和const_cast):

template<class T, bool IsConst>
struct pointer_to_maybe_const;

template<class T>
struct pointer_to_maybe_const<T, true> { typedef const T* type; };

template<class T>
struct pointer_to_maybe_const<T, false> { typedef T* type; };

template<bool IsConst>
struct C_fields {
   typename pointer_to_maybe_const<int, IsConst>::type i;
   // repeat for all fields
};


template<class Derived>
class const_C_base {
public:
    int method() const { // non-mutating method example
        return *self().i;
    }
private:
    const Derived& self() const { return *static_cast<const Derived*>(this); }
};

template<class Derived>
class C_base : public const_C_base<Derived> {
public:
    int method() { // mutating method example
        return ++*self().i;
    }
private:
    Derived& self() { return *static_cast<Derived*>(this); }
};


class const_C : public const_C_base<const_C>, private C_fields<true> {
    friend class const_C_base<const_C>;
};

class C : public C_base<C>, private C_fields<false> {
    friend class C_base<C>;
};

如果您实际上只有很少的字段,那么在两个类中复制它们可能比使用结构更容易。如果有很多,但它们都是同一类型,那么直接将该类型作为类型参数传递会更简单,而不必费心const包装模板。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何处理const对象中非常量引用成员的初始化? 的相关文章

  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 为什么从字典中获取时会得到 Action<> 的克隆?

    我有以下字典 private Dictionary
  • 为什么这个二维指针表示法有效,而另一个则无效[重复]

    这个问题在这里已经有答案了 这里我编写了一段代码来打印 3x3 矩阵的对角线值之和 这里我必须将矩阵传递给函数 矩阵被传递给指针数组 代码可以工作 但问题是我必须编写参数的方式如下 int mat 3 以下导致程序崩溃 int mat 3
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐

  • 我有位置,但 z 索引不起作用

    我希望外环位于圆圈后面 但是当我尝试使用时z index它不工作 没有做任何事情 我做了 2 个环 一个环在圆圈的顶部 没有顶部 另一个在圆圈的后面 我无法移动它 我不知道为什么 root size 200px background wid
  • 为什么 Cache::lock() 在 Laravel 7 中返回 false?

    我的框架是 Laravel 7 缓存驱动程序是 Memcached 我想执行原子缓存获取 编辑 放置 为此我使用Cache lock 但它似乎不起作用 这 lock gt get 返回 false 见下文 我该如何解决这个问题 Fort 测
  • 如何用 Gson java 解析这个转义的 Json?

    因此 我收到了以下我无法控制的回复 message someName someLastName has sent you a question parameters firstName someName lastName someLastN
  • Laravel FFMPEG 错误编码使用 Laravel 队列失败

    我在用 php ffmpeg php ffmpeg 0 5 与 Laravel 5 我使用这个库来压缩和转换录制的视频 我先解释一下场景 当我从控制器执行以下代码时 它的工作方式就像魅力一样 ffmpeg FFMpeg create vid
  • Android中逐帧动画导致OutOfMemoryError

    我的 resources drawable 文件夹中有很多图像作为框架 假设大约 200 个 我想使用这些图像来运行动画 最长的动画为80帧 对于某些动画 我可以成功地通过单击按钮来运行动画 但对于某些动画 它会给出 OutOfMemory
  • 在 Java 中使用 WCF WsHttpBinding WebService

    我正在尝试让 Java 客户端与 WCF wshttpbinding WebService 进行通信 但我无法这样做 呼叫要么挂起 要么我得到 musunderstoodheader expcections 我的Web服务只是Visual
  • docker 的 Cron 容器 - 它们实际上是如何工作的?

    我已经使用 docker 几个月了 并且正在致力于对各种不同的服务器映像进行 docker 化 一个一致的问题是许多服务器需要运行 cron 作业 网上有很多关于这个的讨论 包括 Stackoverflow 但我并不完全理解它的机制 目前
  • Laravel 4 虚拟主机和 mod 重写设置

    我已经尝试了几个小时来安装 Laravel 4 并使虚拟主机和路由正常工作 但到目前为止我一直不走运 我提到我正在这样做Windows 7的机器和WAMP 我将描述我已经做过的事情 我已经启用了 rewrite module 使用以下内容更
  • 平台模块之间是否允许循环?

    这是模块声明java rmi module module java rmi requires java base requires java logging exports java rmi activation exports com s
  • 反射类获取任何对象的所有属性

    我需要创建一个函数来获取对象 包括子对象 的所有属性 这是为了我的错误日志记录功能 现在我的代码总是返回 0 个属性 请让我知道我做错了什么 谢谢 public static string GetAllProperiesOfObject o
  • 沙盒环境中 FinderSync 扩展的读写访问权限

    场景 用户右键单击 Finder 中的目录并找到自定义菜单项 单击该项目将告诉我的应用程序打开一个窗口 用户可以在其中完成工作 完成后 需要将文件写入他通过右键单击选择的文件夹 问题 我现在一切都开始工作了 除了最后一部分 扩展程序无法写入
  • Django:如何在通用创建视图上设置隐藏字段?

    我正在运行 Django 1 6 x 为了扩展我的用户 我添加了另一个存储数据的模型 class UserProfile models Model user models ForeignKey User height models Inte
  • 如何在 recyclerview viewholder 中处理许多不同的视图类型

    如果我有 50 种视图怎么办 我的适配器中应该有 50 个静态内部类吗 根据这个答案 yes 我的第一个想法是将每个视图持有者内部类移动到一个单独的公共类中 但它们必须是静态的 那么将每个都封装成一个公共类 使内部类静态 有更好的选择吗 编
  • 使用一个 NPM 命令启动 React-create-app 和 Electron.js

    我有简单的定制入门包react create app and Electron js 我已添加到 package json 文件 scripts electron electron start cross env BROWSER none
  • Rails:使用 Gmail API 发送电子邮件,附件仅返回编码文件而不返回

    我正在尝试使用 gmail API 发送电子邮件 我的 Ruby 代码如下所示 无需附件即可正常运行 client google client user id token Token find by user id user id acce
  • Java HashMap 性能优化/替代方案

    我想创建一个大的 HashMap 但put 性能不够好 有任何想法吗 欢迎其他数据结构建议 但我需要 Java Map 的查找功能 map get key 就我而言 我想创建一个包含 2600 万个条目的地图 使用标准 Java HashM
  • 如何在 C++ 中从文本文件的开头删除字符“”?

    我正在尝试读取一个文本文件 对于每个单词 我会将它们放入二叉搜索树的节点中 但是 第一个字符始终读作 第一个单词 例如 如果我的第一个单词是 This 那么插入到我的节点中的第一个单词是 This 我一直在论坛上寻找修复它的解决方案 有一篇
  • 可见性:隐藏和显示:无之间的性能差异

    我想简化 jQuery Backbone js Web 应用程序中的事情 其中一种简化是我的菜单和对话框小部件的行为 之前我在开始时创建了菜单的 div 框并使用隐藏它们display none opacity 0 当我需要菜单时 我将其样
  • Django 是同步还是异步?

    Django 是同步还是异步 我想知道 Django 框架是同步的还是异步的 我听说过面试问题 他们询问你正在使用的框架是同步还是异步 所以我想知道它的含义同步和异步在网络开发方面 Django 本身是同步的 每个 HTTP 请求都将完全同
  • 如何处理const对象中非常量引用成员的初始化?

    假设你有课 class C int i public C int v i v void method const this method does not change i void method this method changes i