C++ 在C++;,类成员的参考应为常量或非常量
考虑下面这个最小的例子C++ 在C++;,类成员的参考应为常量或非常量,c++,reference,constants,const-cast,C++,Reference,Constants,Const Cast,考虑下面这个最小的例子 #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<i
#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;
}
原因对我来说很清楚:const关键字对我在第8行的演员阵容感到不安。问题是:有时我确实需要带有std::vector
的数据类,但有时需要带有const std::vector
的数据类。比如有两个类:一个用于读入数据
,另一个用于读入数据
。但是,我不喜欢用几乎冗余的函数编写两个数据类。我的问题是:
- 你能给我一个很好的解决方案来实现我在
中尝试做的事情吗?C++11解决方案也非常受欢迎:)main()
- 这就是使用
和迭代器
的原因吗常量迭代器
- 您得到的错误大致如下:
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>’
另一种选择是使用非引用成员:
#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!
};
#包括
类数据
{
std::向量v;
公众:
数据(std::vector&_v):v(_v){}
数据(const std::vector&_v):v(_v){}//错误!
};
const
-需要在编译时知道数据成员的属性。如果“有时”需要引用常量
向量,有时需要引用非常量
,则应使用包含公共功能的基本抽象类创建类层次结构,并将其继承到两个数据
类中:数据
和常量数据
。Data
将包含一个非const
向量,ConstData
将包含一个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;
}
};
类抽象数据{
公众:
//常用函数使用vect()和const_vect()
void common_function1();
无效公共_函数2();
受保护的:
虚拟向量&vect()常量=0;
虚拟常量向量&const_vect()常量=0;
};
类数据:公共抽象数据{
向量&v;
公众:
数据(向量&_-v):v(_-v){}
受保护的:
向量&vect()常量{
返回v;
}
常量向量&常量向量()常量{
返回v;
}
};
类ConstData:公共抽象数据{
常数向量&v;
向量温度;
公众:
常数数据(常数向量&_v):v(_v){}
受保护的:
向量&vect()常量{
return temp;//您可以选择抛出异常
}
常量向量&常量向量()常量{
返回v;
}
};
请注意,此类层次结构可能需要析构函数和各种副本构造函数,具体取决于用法。注意:我目前正在考虑将std::vector
制作为模板,但这是最佳解决方案吗?:)请注意:我在main()中将c_v更改为常量向量。虽然我认为这对你的代码有效。你的代码有效,但我需要数据
类有时具有v
常量。所以这不是解决方案:(在这种情况下,您应该参考@dasblinkenlight的答案。很好的推理!所以我使用模板的想法还不错?在这里使用CRTP而不是虚拟函数可能是一个很好的练习?:)@Johannes基于模板的解决方案的一个问题是,您无法轻松区分常量类型t
和非常量类型。如果模板的某些函数需要以非常量方式访问向量,则整个模板将无法编译。基于模板的解决方案将从“不可变”数据模板类继承一个“可变”数据模板类,并向其添加可变函数。我不能100%确定是否得到了该类。如果我要存储多个对象,我会使用类型列表或类似的东西。这不应该在编译时设置类型吗?@Johannes是的,这将在编译时设置类型。问题是,如果类型恰好是const
,并且模板的某些方法需要非const访问,那么这些方法将无法编译。
#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!
};
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;
}
};