【问题标题】:C++: Copying pointer to const object into non-const object pointerC ++:将指向常量对象的指针复制到非常量对象指针中
【发布时间】:2021-06-19 08:19:04
【问题描述】:

在我的自定义类中,将输入变量指针声明为常量并将其复制到非常量成员变量指针时出现错误。

我得到的错误是:

无法使用“Position *”类型初始化成员子对象 'const Position *' 类型的左值

为什么会这样?为什么这与其他成员变量(_attack)不一致?它只是复制指针(地址)的值,就像复制 int (_attack) 的值一样。

class Creature
{
private:
  int _attack;
  Position* _position;
public:
  Creature(const int attack, const Position* position)
      : _attack{attack}, _position{position} // ERROR: Cannot initialize a member subobject of type 'Position *' with an lvalue of type 'const Position *'
  {}
};

【问题讨论】:

  • position 是一个指向常量Position 的指针。指针本身不是常量
  • 是一致的。 _attack 获得attack 的副本,_position 获得position 的副本。但是,position 是指向 const 对象的指针,_position 不是。
  • 知道了,谢谢大家。这是一个微妙但重要的区别,我一定把它和 Position* const (指向位置的常量指针)混淆了
  • 并不总是对 C++ 代码有帮助,但对于 const 指针与指向 const 的指针,它确实有帮助:cdecl.org

标签: c++ class oop pointers constants


【解决方案1】:

指针有两种“类型”const。他们是

const T * pointer_name

T * const pointer_name

也可以组合成第三种也是最后一种形式

const T * const pointer_name

使用第一个,您正在创建一个指向const T 的指针。这就是您在构造函数中所拥有的。这违背了_position 的类型,即T *,或者更确切地说,是指向非常量T 的指针。这就是您收到错误的原因。您不能将指向 const T 的指针的值分配给指向非 const T 的指针。

使用第二种形式,您的代码可以编译,因为现在您没有指向const T 的指针,而是有一个指向Tconst 指针。两个指针都指向一个非常量的东西,所以可以将一个分配给另一个

这与attack 发生的事情相同。虽然它可能是 const,但您仍然可以复制它的值并将其放入另一个对象中。

最后一个形式是一个const 指向const T 的指针,并且由于与第一个 from 不起作用的原因相同的原因,这里不再起作用。


这也进入了东海岸与西海岸的 const 风格。上面的西海岸风格,有时不是那么容易理解的类型。相反,您可以使用东海岸风格,如

T const * pointer_name
T * const pointer_name
T const * const pointer_name

现在他们都从右到左准确地读取类型是什么。

【讨论】:

  • 谢谢内森!
【解决方案2】:

对于构造函数的attack 参数(声明为const),您正在复制赋予成员变量(_attack)的值,即不是 const;但是,该成员变量的后续修改不会更改传递参数的值,因此您没有“违背您所做的承诺”。

但是,在position 参数的情况下,情况就大不相同了:这里的const 限定符指出它指向一个无法修改的对象;但是,如果您将该指针的值(即地址)复制到非常量成员变量,那么您将允许修改引用的对象。所以,编译器(正确地)告诉你不能这样做。

如果您实际上想要的是传递一个指针,它是一个不可变地址,但传递给一个可以更改的对象,那么你需要在构造函数的参数中移动const关键字:

    Creature(const int attack,  Position* const position) // POINTER is const, POINTEE is not!

【讨论】:

  • 谢谢阿德里安!
【解决方案3】:

第一个参数不引用构造函数范围之外的任何内容,因为它只是一个副本。这种情况下的 const 只是说您的构造函数本身不允许更改 attack 的值。

第二个参数是指向const Position 的指针。如果您可以将其分配给非常量 Position*,那么您可以通过非常量指针改变该位置。如果允许这样做,那么如果某人有一个不想被您的构造函数更改的 Position 指针,则他们将无法创建您的类的实例。

请注意,您可以通过将第二个参数更改为Position* const position 来使第二个参数的行为与第一个参数相同。这使得指针 const 但不是它指向的对象。

请参阅this 相关问题。

【讨论】:

  • 谢谢院长。为了与我的函数声明保持一致,并使输入参数不可更改,这是否意味着我必须使用“Position* const position”声明它?
  • @MichelHeusser 是的,没错。
猜你喜欢
  • 2016-07-18
  • 1970-01-01
  • 2014-02-23
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2020-10-23
  • 2017-06-12
相关资源
最近更新 更多