我有一个带有构造函数的类,该构造函数接受一个非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引用,然后可以用于每个有问题的案例。
答案 0 :(得分:2)
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
的引用,这是未定义的行为。
这是一个小demo:
int x = 10;
cout << x << endl;
const foo f(x);
f.bar();
cout << x << endl;
打印
10
5
答案 1 :(得分:0)
您正试图放弃const
ness:
const A create_const_a(const double &dd, const int &ii) {
return A(dd,ii);
}
但是dd
是非const的,因此创建的对象A
不会知道它不能修改它的d
成员,而create_const_a
的调用者会通过变量相信如此。
你无法复制dd
,或放弃const
(例如通过const_cast
)这是危险的,并强烈表明设计中存在错误。< / p>
您对A
的定义说“我需要能够修改d
”,但在create_const
中您保证不会修改它。
换句话说,您应该解决设计中的错误。释放约束或制作副本。让“错误消失”只会使糟糕设计的症状变得沉寂,直到你在违反合同时遇到真正的麻烦时才会产生影响。
答案 2 :(得分:0)
函数const A create_const_a
将ref作为const double的第一个参数,然后尝试在ctor中使用它作为非const ref,这是不允许的。
您应该在此处删除const
限定符。
如果您确定可以在此处执行此操作,则表示如果您确定create_const
将始终接收非const参数,则可以明确使用const_cast
删除限定符:
const A create_const_a(const double &dd, const int &ii) {
return A(const_cast<double &>(dd),ii);
}
但 BEWARE ,如果您对最初声明为const的变量执行此操作,则会导致未定义的行为。