В C ++ ссылка в качестве члена класса должна быть постоянной или неконстантной

Рассмотрим следующий минимальный пример.

#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?

3

Решение

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;
}
};

Обратите внимание, что для этой иерархии классов может потребоваться деструктор и различные конструкторы копирования, в зависимости от использования.

2

Другие решения

Ошибка, которую вы получили, была такой:

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!
};
1

По вопросам рекламы [email protected]