使用 non-const 构造 const 对象
Constructing const object using non-const
我有一个带有构造函数的类,该构造函数接受分配给该类成员的非常量引用。现在我想创建该类的 const 对象,但是如果我将 const 引用传递给构造函数,构造函数会抱怨。下面的代码是对我原始代码的简化,演示了这个问题。
据我所知,创建一个 const 对象应该没有问题,因为它是基于 const 数据的?
如何在create_const_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;
}
我得到的错误是:
test.cc: In function ‘const A create_const_a(const double&, const int&)’:
test.cc:27:17: error: binding ‘const double’ to reference of type ‘double&’ discards qualifiers
return A(dd,ii);
^
test.cc:8:3: note: initializing argument 1 of ‘A::A(double&, const int&)’
A(double &dd, const int &ii)
^
更新:在学习了一些关于 const 如何处理其中的对象和非 const 引用的新知识后,我最终通过引入另一种类型解决了原始问题,比如 ConstA
只包含 const 引用,然后可以在每个有问题的情况下使用。
C++禁止这样做,以避免将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
的引用,这是未定义的行为。
这是一个小演示:
int x = 10;
cout << x << endl;
const foo f(x);
f.bar();
cout << x << endl;
它打印
10
5
const A create_const_a
将常量双精度的引用作为第一个参数,然后尝试在ctor中将其用作不允许的非常量引用。
应在此处删除const
限定符。
真的确定为什么你可以在这里这样做,这意味着如果你可以确定create_const
将全部接收非常量参数,你可以显式使用 const_cast
来删除限定符:
const A create_const_a(const double &dd, const int &ii) {
return A(const_cast<double &>(dd),ii);
}
但请注意,如果您在最初声明为 const 的变量上执行此操作,这将导致未定义的行为。
你试图放弃const
:
const A create_const_a(const double &dd, const int &ii) {
return A(dd,ii);
}
但是dd
是一个非常量,所以创建的对象A
不知道它不能修改它d
成员,而create_const_a
的调用者会传递变量。
你不能不复制dd
,或者放弃const
(例如通过const_cast
),这是危险的,强烈表明设计中的错误。
你对A
的定义是"我需要能够修改d
",但在create_const
你承诺它不会被修改。
换句话说,您应该解决设计中的错误。释放约束或创建副本。让"错误消失"只会消除糟糕设计的症状,直到当违反合同最终产生影响时,你会陷入真正的麻烦。
- 被解释为低级别const的const对象的地址
- 使用共享指针的函数调用,其对象应为 const
- 如何从构造函数副本 T(const T&)调用对象 T?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 无法使用类型 'const char *' 的左值初始化类型 'char *' 的成员子对象
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- "this"指向的对象是否与 const 对象相同?
- const auto & 和 auto & if reference 对象之间的区别是 const
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 为什么 const YAML::Node 对象的行为不像 yaml-cpp 中的类似值的对象?
- 从 const 对象访问非 const 方法
- 将非 const 对象用于 const 参数
- 如何键入用于const对象的自定义io操纵器
- 对临时对象的Const引用不会延长其生存期
- 正在通过const-ref未定义的行为捕获新构造的对象
- 具有成员变量的对象 Const 数组 = 先前索引成员变量的总和
- 为什么我构建的临时对象const不可变
- 强制用户声明对象const