初始化常量对象中的引用
Initialising a reference in a const object
我有以下代码:
class c_int {
public:
int &i;
c_int(int &in) : i(in) {
};
c_int(const int &in) : i(in) {
};
};
int main (void) {
const int i = 10;
const c_int c(i);
std::cout << c.i << std::endl;
return 0;
}
编译它会给出以下错误消息:
tmp.cpp:12:30: error: invalid initialization of reference of type 'int&' from ex
presion of type 'const int'
我遇到了一点麻烦,弄清楚如何实现这一点,我应该如何初始化const对象内的引用?
编辑:理想情况下,我希望这个对象也能用于非常量;当对象未声明为const时。
进一步编辑:
我也希望使用这样的对象:
int main (void) {
int i = 10;
c_int c(i); // for some reason this calls the 2nd of my constructors, does name mangling not take const into account?
c.i = 9;
std::cout << i << std::endl;
return 0;
}
问题不在于您的对象是const
:而是您试图将常量引用绑定到非常量引用:这是非法的。
您可以将const引用绑定到const成员:
class c_int {
public:
const int &j;
c_int(const int &in) : j(in){ };
};
int main (void) {
const int i = 10;
c_int c(i);
std::cout << c.j << std::endl;
}
您仍然可以为const
和non const
对象使用两个不同的类,或者如果您确实需要一个类并且知道自己在做什么,请使用const_cast
(非常不鼓励:任何修改对象的尝试都将是未定义的行为):
class c_int {
public:
int& i;
c_int(int& in) : i(in){ }
c_int(const int& in) : i(const_cast<int&>(in)){ } // Very wrong
};
或者,忘记通过引用传递并使用值语义:
class c_int {
public:
int i;
c_int(int in) : i(in){ }
};
编辑:
对于int参数不是const:的情况,您仍然可以添加一个使用非const引用的构造函数
class c_int {
public:
const int &j;
c_int(const int &in) : j(in){ };
c_int(int &in) : j(in){ }
};
int main (void) {
const int i = 10;
const c_int c(i);
std::cout << c.j << 'n';
int i2 = 11;
const c_int d(i2);
std::cout << d.j << 'n';
}
现场演示
我建议您有两个不同的类。一个保存常量引用,另一个保存非常量引用。这类似于标准容器将iterator
和const_iterator
作为两个独立类的方式。
class c_int {
public:
int &i;
c_int(int &in) : i(in) {};
};
class const_c_int {
public:
int const &i;
c_int(int const &in) : i(in) {};
};
如果你想避免重复代码,你可以制作一个模板:
template<typename T>
class c_generic {
public:
T& i;
c_generic(T& in) :i(in) {}
};
typedef c_generic<int> c_int;
typedef c_generic<int const> const_c_int;
您希望同一类c_int
作为常量引用,而对int
的非常量引用取决于c_int本身的"constness"。不幸的是,这在C++中是不可能的。由于相同的原因,例如iterator
和const_iterator
在STL中是不同的类型。不过,您可以使用相同的方法:
class c_int {
public:
int &j;
c_int( int &in) : j(in){ }
};
class const_c_int {
public:
const int &j;
const_c_int( const int &in) : j(in){ }
const_c_int( const c_int &in) : j(in.j){ }
};
因此,您可以将c_int
转换为const_c_int
,但不能将其转换为
引用成员必须是或不是const
。const
对象的构造函数不可能与非const
对象的构造函数不同。
一种选择是实际上有两个不同的类,一个用于包装int,另一个用于封装const。类似于CCD_ 16和CCD_。这可以通过模板参数,也可以从常量版本派生非常量版本,或者它们可以完全独立。
要使用单个非模板类,您需要使用一个返回引用的函数,以便根据对象是否为const
重载它。此外,它必须是在运行时检查的属性,因为总是可以将非常量对象强制转换为常量。例如:
class c_int
{
private:
int const *p_int;
bool is_const;
public:
c_int(int &x): p_int(&x), is_const(false) {}
c_int(int const &x): p_int(&x), is_const(true) {}
int &i()
{
if ( is_const )
throw std::runtime_error("non-const access for const int");
return const_cast<int &>(*p_int);
}
int const &i() const { return *p_int; }
};
可以有一个默认的构造函数,它什么都不做,然后使用一个函数来设置可变的类成员,但这样就失去了构造函数的好处。
我认为您混淆了const
的含义。引用始终是常量(无论是否从const
对象访问):您不能更改引用,并且作为类成员,它必须在构造函数的initializer列表中初始化。
这种情况与指针的情况相当。考虑:
const int*a; // pointer to a const int: cannot change *a, but can change a
int*const b; // pointer to an int, cannot change b, but can change *b
const int*const c; // constant pointer to a constant int: cannot change c nor *c
int&x; // equivalent to pointer b
const int&y; // equivalent to pointer c
引用总是恒定的,因此具有指针的第二个const
总是打开的。
- 引用对象成员函数的成员函数
- 从 Base 引用对象调用派生类的成员
- 转换引用对象的边界框?
- 现代编译器会优化只引用对象子集的局部变量吗
- l值引用对象上的Constexpr成员函数:Clang和gcc不同意
- 将 const 类型引用对象注册为类成员对象C++
- Boost Intervocess:通过迭代通过从结构引用对象的映射进行迭代时
- 无法用2D矢量成员引用对象
- 在由引用对象传递中访问由引用对象传递的变量
- 如何使用QString引用对象名称
- 使用自动迭代器引用对象
- C++ 在另一个对象中引用对象的当前状态
- 使用共享对象和引用对象进行引用计数
- 未显式引用对象的全局对象构造函数在最终二进制文件 - LD 中被丢弃
- 引用对象的动态类型何时可以更改
- 引用对象内部的指针
- C++从全局静态函数中引用对象
- C++如何仅在没有其他人直接或间接引用对象指针时删除该指针
- 如何使用C++引用对象
- 为什么引用对象仅保存特定类型的引用