Рассмотрим следующий минимальный пример.
#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. Проблема: мне действительно иногда нужен класс Data с std::vector
, но иногда с const std::vector
, Как два класса: один для чтения в Data
и один для чтения из Data
, Однако я не люблю писать два класса данных с почти избыточными функциями. Мои вопросы:
main()
? Решения C ++ 11 тоже приветствуются 🙂iterator
а также const_iterator
?const
-чность членов данных должна быть известна во время компиляции. Если вам «иногда» нужна ссылка на const
вектор и иногда неconst
, вы должны создать иерархию классов с базовым абстрактным классом, содержащим общую функциональность, и наследовать его в двух Data
классы: Data
а также ConstData
, Data
будет содержать неconst
вектор и ConstData
будет содержать const
вектор. Таким образом, вы не будете дублировать какую-либо логику, в то время как два отдельных класса будут содержать две ссылки на разные const
-ness.
Вот пример:
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!
};