Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用非常量构造常量对象_C++_Constructor_Constants - Fatal编程技术网

C++ 使用非常量构造常量对象

C++ 使用非常量构造常量对象,c++,constructor,constants,C++,Constructor,Constants,我有一个带有构造函数的类,它接受分配给类成员的非常量引用。现在我想为这个类创建一个const对象,但是如果我向构造函数传递一个const引用,构造函数就会抱怨。下面的代码是对我的原始代码的简化,它演示了这个问题 就我所知,创建const对象应该没有问题,因为它是基于const数据的 如何实现我在create\u const\u a中的目标 #include <iostream> class A { private: double &d; const int &

我有一个带有构造函数的类,它接受分配给类成员的非常量引用。现在我想为这个类创建一个const对象,但是如果我向构造函数传递一个const引用,构造函数就会抱怨。下面的代码是对我的原始代码的简化,它演示了这个问题

就我所知,创建const对象应该没有问题,因为它是基于const数据的

如何实现我在
create\u const\u a
中的目标

#include <iostream>

class A {
private:
  double &d;
  const int &i;
public:
  A(double &dd, const int &ii)
    : d(dd), i(ii)
  {}

  void set_d(double a) {
    d = a;
  }

  void print() const {
    std::cout << d << " " << i << std::endl;
  }
};


A create_a(double &dd, const int &ii) {
  return A(dd,ii);
}

const A create_const_a(const double &dd, const int &ii) {
  return A(dd,ii);
}


void foo(A a)
{
  a.set_d(1.3);
  a.print();
}

void bar(const A a)
{
  a.print();
}


int main(int argc, char *argv[])
{
  double d = 5.1;
  int i = 13;

  foo(create_a(d,i));

  bar(create_const_a(d,i));

  return 0;
}


更新:在学习了一些关于const如何处理对象和对象中的非const引用的新知识之后,我最终通过引入另一种类型解决了原来的问题,比如说
ConstA
,它只包含const引用,然后可以在每个有问题的情况下使用。

C++禁止这样做,以避免将
const
引用转换为非const

下面是一个小例子,说明了这将如何发生:

struct foo {
    int& a;
    foo(int& b) : a(b) {}
    void bar() const {
        a = 5;
    }
};
上面的编译很好,因为
a=5
不会更改
foo
对象的状态;它更改外部
int
的状态,因此
foo::bar
允许为
const

现在假设我们可以这样做:

const foo make_const(const int& x) {
    return foo(x); // Not allowed
}
这样我们就可以写作了

const foo f(make_const(10));
f.bar();
并修改对临时
int
的引用,这是未定义的行为

下面是一个小例子:


您正试图删除
const
ness:

const A create_const_a(const double &dd, const int &ii) {
  return A(dd,ii);
}
但是
dd
是一个非常量,因此创建的对象
a
不会知道它不能修改它的
d
成员,而
create\u const\u a
的调用者则会这样传递变量

您必须复制
dd
,或删除
const
(例如,通过
const\u cast
),这是危险的,并强烈表明设计中存在错误

您对
A
的定义是“我需要能够修改
d
”,但在
create\u const
中,您承诺不会修改它


换句话说,您应该解决设计中的错误。释放约束或制作副本。使“错误消失”只会使糟糕设计的症状消失,直到违反合同的行为最终引起反响时,你会陷入真正的麻烦。

函数
const A create\u const\u A
将常量double的ref作为第一个参数,然后尝试将其作为非常量ref使用,这是不允许的

您应该在此处删除
const
限定符

如果您确实确定为什么可以在此处执行此操作,这意味着如果您可以确保
create\u const
始终接收非常量参数,则可以明确使用
const\u cast
删除限定符:

const A create_const_a(const double &dd, const int &ii) {
  return A(const_cast<double &>(dd),ii);
}
const A create_const_A(const double&dd,const int&ii){
返回A(const_cast(dd),ii);
}

但是,请注意,如果对最初声明为常量的变量执行此操作,将导致未定义的行为。

可以从非常量转换为常量,但不能从非常量转换为常量。构造函数需要一个非常量,而您的
create\u const\u a
将接收一个常量。所有这些引用。。。如果你继续,你迟早会找到一个指针,在那里你有一个悬而未决的引用,坏事就会发生。为什么在
A
类中有引用?您试图用这样的解决方案解决的实际问题是什么?您的
create\u const\u a
方法返回对本地对象的引用。这不像你想象的那样有效。有关详细信息,请参阅。@FrançoisAndrieux No它返回对临时对象的引用。幸运的是,它是一个
const
引用,它延长了对象的生命周期,直到使用它的表达式结束。这仍然不是一个好主意,但在这个非常特殊的情况下它会起作用。好吧,返回对局部变量的引用显然是无效的,但不知何故,返回const引用似乎很好。但这是一个单独的讨论,不影响当前的问题。我现在更新了这个问题以删除它。引用可以在不违反常量正确性的情况下更改这一事实对我来说是全新的,并解释了为什么这似乎是不可能的。@kalj这是
const
-ness应用于引用和指针时最棘手的部分。指针或引用可以是
const
,而它们指向/引用的项将保持可写状态。
10
5
const A create_const_a(const double &dd, const int &ii) {
  return A(dd,ii);
}
const A create_const_a(const double &dd, const int &ii) {
  return A(const_cast<double &>(dd),ii);
}