在C++中,作为类成员的引用应为常量或非常量

In C++, reference as class member shall be const or non-const

本文关键字:常量 引用 非常 C++ 成员      更新时间:2023-10-16

考虑以下最小示例。

#include <vector>
class Data
{
std::vector<int>& v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};
int main()
{
std::vector<int> v;
const std::vector<int> c_v;
Data d(v);
Data const_d(c_v);
return 0;
}

这不会编译。下面是g++ -Wall的全部输出。

const.cpp: In constructor ‘Data::Data(const std::vector<int>&)’:
const.cpp:8:41: error: invalid initialization of reference of type ‘std::vector<int>&’ from expression of type ‘const std::vector<int>’

原因我很清楚:const关键字对我在第8行中的角色扮演感到不安。问题是:我有时确实需要带std::vector的Data类,但有时需要带const std::vector的Data类。比如有两个类:一个用于读入Data,另一个用于从Data读入。然而,我不喜欢编写两个具有几乎冗余函数的Data类。我的问题:

  • 你能给我一个很好的解决方案来实现我在main()中尝试做的事情吗?C++11解决方案也非常受欢迎:)
  • 这就是iteratorconst_iterator的原因吗

const-数据成员的数量需要在编译时知道。如果"有时"需要对const向量的引用,有时需要对非const的引用,则应该创建一个类层次结构,该类具有包含公共功能的基本抽象类,并在两个Data类中继承它:DataConstDataData将包含非const向量,而ConstData将包含const向量。这样就不会复制任何逻辑,而两个独立的类将包含两个不同const性质的引用。

这里有一个例子:

class AbstractData {
public:
// Common functions use vect() and const_vect()
void common_function1();
void common_function2();
protected:
virtual vector<int>& vect() const = 0;
virtual const vector<int>& const_vect() const = 0;
};
class Data : public AbstractData {
vector<int>& v;
public:
Data(vector<int>& _v) : v(_v) {}
protected:
vector<int>& vect() const {
return v;
}
const vector<int>& const_vect() const {
return v;
}
};
class ConstData : public AbstractData {
const vector<int>& v;
vector<int> temp;
public:
ConstData(const vector<int>& _v) : v(_v) {}
protected:
vector<int>& vect() const {
return temp; // You can choose to throw an exception instead
}
const vector<int>& const_vect() const {
return v;
}
};

注意,根据使用情况,这个类层次结构可能需要析构函数和各种复制构造函数。

您得到的错误是:

foo.cpp: In constructor ‘Data::Data(const std::vector<int>&)’:
foo.cpp:8:44: error: invalid initialization of reference of type ‘std::vector<int>&’ from expression of type ‘const std::vector<int>’

因为您正试图创建一个对数据的非常数引用,您(Data)承诺您的调用者将被视为const

以下是一个将const引用声明为Data成员的解决方案:

#include <vector>
class Data
{
const std::vector<int> &v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};
int main()
{
std::vector<int> v;
std::vector<int> c_v;
Data d(v);
Data const_d(c_v);
return 0;
}

另一种选择是使用非参考成员:

#include <vector>
class Data
{
std::vector<int> v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};