`const`ness,引用和函数调用

时间:2013-04-02 20:39:33

标签: c++ pointers inheritance reference

class Foo{};

class BarParent
{
    Foo* p_foo;

    public:
    BarParent(Foo * const p_x) //OR BarParent(Foo const * x) OR BarParent(Foo * x)
                             //OR (Foo const * const x)
    {
        p_foo = x;
    }
};


class BarChild: public BarParent
{
    public:
    BarChild(const Foo& x)
    : BarParent(& x){}
};

我打算:在使用x ctor时,使用p_foo指向BarChild。有没有办法这样做。

我已经为BarParent ctor尝试了所有可能的签名而没有运气。

摘要: 出于某种原因,我混淆了将(指向非const对象的指针)分配给({{1的指针)的事实对象)打破const限制。

3 个答案:

答案 0 :(得分:3)

我向您介绍两种选择:

  1. 要么你真的希望BarChild构造函数采用const Foo&,在这种情况下你需要坚持你永远不会允许Foo对象的承诺改性。为此,p_xp_foo都必须为const Foo*(即指向const Foo的指针)。如果它是指向非const Foo的指针,那么您将有效地修改对象,从而违背您的承诺。

    class BarParent
    {
        const Foo* p_foo;
    
        public:
        BarParent(const Foo* p_x)
        {
            p_foo = x;
        }
    };
    
  2. 或者,您确实希望保留Foo*而不是const Foo*,因此BarChild构造函数应该使用Foo&而不是const Foo& const。这样,您就不会说谎保留对象class BarChild: public BarParent { public: BarChild(Foo& x) : BarParent(& x){} };

    {{1}}

答案 1 :(得分:2)

您误解了const Foo&是什么。

const Foo&是变量的别名或引用,通过该变量,您永远不能对其进行修改(不使用const_cast或C样式转换)。它不仅仅是一个不“立刻”修改它的承诺,但它也是一个承诺,你告诉这个变量的每个人都不会修改它。

如果您希望存储指向此数据的指针以便稍后修改,则不应将其作为const Foo&,而是Foo&

因此,要修复代码,请按以下方式重写BarChild

class Foo{};

class BarParent
{
  Foo* p_foo;

  public:
    BarParent(Foo * p_x):
      p_foo(p_x)
    {}
};

class BarChild: public BarParent
{
  public:
  BarChild(Foo& x):
    BarParent(& x)
  {}
};

答案 2 :(得分:1)

你可以用const_cast

抛弃常数
p_foo = const_cast<Foo *>x;

但这通常是一个坏主意,原因有两个:

  • const-correctness的重点是记录/强制执行某些关于谁可以修改内容的期望。 const_cast颠覆了这一点。

  • 在某些情况下,您甚至可以释放未定义的行为(即,通过非const指针修改真正为const的基础对象)。

一般来说,找到一种方法来避免首先需要这样做(我不能提出任何具体的建议,因为我不知道你的用例是什么)。