非 const 类处理的数据的 const 正确性

Posted

技术标签:

【中文标题】非 const 类处理的数据的 const 正确性【英文标题】:Const correctness for data handled by not const classes 【发布时间】:2017-06-07 15:44:43 【问题描述】:

我想使用面向类的设计来高效、干净地处理嵌入式平台上的数据。我不应该在堆栈上创建新对象(或者至少是非常经济的),所以我打算将我的数据作为参考传递给辅助类并在其中操作它(也为了实现适当的封装)。

以下代码是我面临的问题的一个非常精简的示例。

#include "Vector.h"

void DoSomething(float* a1, const float* a2)

  // some code

  Vector v1(a1[0], a1[1], a1[2]);
  Vector v2(a2[0], a2[1], a2[2]);
  v1.MakeEqual(v2);

  // more code


int main()

  float x1[3] =  0, 0, 0 ;
  float x2[3] =  1, 1, 1 ;
  DoSomething(x1, x2);
  return 0;

Vector-Class 在头文件中定义:

#pragma once
class Vector

public:
  Vector(float& _x, float& _y, float& _z) :x(_x), y(_y), z(_z)
  

  Vector(const float& _x, const float& _y, const float& _z) 
      :x(const_cast<float&>(_x)), y(const_cast<float&>(_y)), z(const_cast<float&>(_z)) //works, but looks not good
  

  ~Vector();

  void MakeEqual(const Vector& other)
  
    x = other.x;
    y = other.y;
    z = other.z;
  

private:
  float& x;
  float& y;
  float& z;
;

我的数据在外部某个地方定义(main-function),然后作为指向函数DoSomething 的指针传递。在这个函数内部,向量对象被包裹在数据周围,以帮助做一些向量典型的事情(旋转、叉积等)。现在我想要 const 正确并传递不打算更改为 const 的数据,但是当创建向量 v2 时,我让编译器抱怨他 cannot convert argument 1 from 'const float' to 'float &amp;'。我明白他想说什么,但我该如何解决呢?向量方法仅在我在向量上使用时才有意义,但向量v2 的构造函数不知道我实际上并没有在处理 v2 的数据。

解决此问题的一种方法是在第二个构造函数中使用 const_cast 的代码中显示,但我觉得这不是一种好的风格,因为我正在丢弃我的合法 const 数据。另一种方法是定义第二类ConstVector,但这似乎也很奇怪。

我不得不提一下,由于编译器的限制,我必须遵守C++03 标准,所以很遗憾我不能使用太现代的语言功能。 stl-containers 也(可能)不可用,因为我无法控制分配内存的方式、时间和地点。

【问题讨论】:

您的MakeEqual 正在更改x,y,z,因此您可以(能够)更改值。 虽然不建议在这种情况下使用,但您可以使用 class const_vector 之类的内容与 const 值一起使用。 【参考方案1】:

你有:

Vector(float& _x, float& _y, float& _z) :x(_x), y(_y), z(_z)

这不好用。例如,您不能使用:

Vector v1(0, 0, 0);

另外,你不能使用

Vector v1(a1[0], a1[1], a1[2]);

因为a1[0] 的计算结果为const float&amp;,而不是float&amp;

那是设计糟糕的界面。将参数更改为简单值:

Vector(float _x, float _y, float _z) :x(_x), y(_y), z(_z)

【讨论】:

我猜 OP 希望 Vectors 充当包装器(可以更改原始数组),因此 Vector::Vector(float,float,float) 可能无法满足 OP 的需求(对于 v1)。 @appleapple,我希望不会。在堆栈上使用临时对象,例如Vectors,对于执行他们希望执行的计算类型没有多大帮助。我会等待 OP 澄清。 @appleapple,你是对的。我只使用 Vector 类以某种方式操作现有数据。在我这样做之后,我可以完全忽略该向量,因为它本身不包含数据。可以将数据作为建议的值传递,最后将向量运算的结果复制回数据。堆栈上的负载更多,但可能比我目前的解决方案更好......

以上是关于非 const 类处理的数据的 const 正确性的主要内容,如果未能解决你的问题,请参考以下文章

防止 const 类函数在引用成员上调用非 const 类函数

C++ 中的 const 正确性

当容器在 C++ 中为 const 时,如何对容器持有的对象进行非 const 访问

类的const成员

c++学习总结------类结构学习

Flutter 无法为具有非最终字段的类定义 const 构造函数