问题
Suppose I have
class A final {
int& ir;
public:
A(int& x) : ir(x) { }
void set(int y) { ir = y; } // non-const method!
int get() const { return ir; }
};
and
const int i;
Obviously I can't have
A a(i);
since that would breaks constness. But I also cannot have
const A a(i);
despite the fact that this will not break constness de-facto. C++ doesn't support "const-only" ctors, e.g. in this case one which would take a const int&
. Is there a way to get const A a
wrapping a reference to i
- other than
A a(const_cast<int &>(i))
?
回答1:
"Const" means that the object is constant during between the constructor end and destructor begin (during construction, you must be able to change the object). C++ doesn't have a "preparation constructor" of sorts that is preferred for const objects.
You can try this workaround by applying boost::variant
. This is not completely type-safe at compile time, but detect errors at runtime by throwing an exception at least.
#include <boost/variant.hpp>
#include <iostream>
class R {
boost::variant<int&, const int&> v;
public:
R(int&v):v(v) { }
R(const int&v):v(v) { }
// works with both
int get() const {
return boost::apply_visitor(
[](int x){return x;}, v);
}
// only works for non-const A. If at construction, a const
// int was passed, throws an error at runtime
void set(int x) {
boost::get<int&>(v) = x;
}
};
int main() {
int a = 0;
const int b = a;
R r1(a);
R r2(b);
const R r3(a);
std::cout << r1.get() << r2.get() << r3.get();
// r3.set(1); // compile error
r1.set(1); // works
r2.set(1); // runtime error
}
回答2:
C++ doesn't have a concept of fully constant classes, and compiler may not perform if reference int &
is used only as const int &
. So basically, you cant do it.
回答3:
It's weird but
class A final {
union{
int& ir;
const int ○
};
public:
A(int& x) : ir(x) { }
A(const int& x) : cir(x) { }
void set(int y) { ir = y; } // non-const method!
int get() const { return ir; }
};
int main(int argc, char *argv[])
{
const int cv = 8;
int v = 6;
A a( cv );
std::cout << a.get() << std::endl;
a.set( v );
std::cout << a.get() << std::endl;
return 0;
}
Also your set and get method opearates on values not references, so it's looks like you a doing something wrong
回答4:
This is not how I would write the code but it somehow works. If you construct a template class from the const variable, the set() function is defined also const and does not change the state. By constructing from non-const variable, the set function is able to change the state.
#include <iostream>
#include <string>
#include <type_traits>
template<typename T>
class A
{
T &_i;
public:
A(T &i) : _i(i) {}
template <typename D = T,
typename = std::enable_if_t<std::is_const<D>::value
>
>
void set(T i) const { std::cout << "Do nothing on set" << std::endl; }
template <typename D = T,
typename = std::enable_if_t<!std::is_const<D>::value>
>
void set(T i) { std::cout << "Do something on set" << std::endl; }
};
int main()
{
{
std::cout << "Construct from NON const variable" << std::endl;
int b = 5;
A<decltype(b)> a(b);
a.set(3);
}
{
std::cout << "Construct from const variable" << std::endl;
int const b = 5;
A<decltype(b)> a(b);
a.set(3);
}
}
This prints:
Construct from NON const variable
Do something on set
Construct from const variable
Do nothing on set
回答5:
class A {
const int& ir; // <<-- it's a const int.
/* ... */
public:
A(int& x) : ir(x) { }
};
来源:https://stackoverflow.com/questions/36773397/if-class-a-modifies-its-construction-parameters-can-i-initialize-const-as-with