#c #operator-overloading #overloading #shared-ptr #square-bracket
#c #оператор-перегрузка #перегрузка #shared-ptr #квадратная скобка
Вопрос:
В настоящее время я создаю свой собственный векторный класс, и мне нравится создавать экземпляры любого класса с помощью общих указателей. Итак, есть ли способ перегрузки operator[]
для достижения следующего кода?
class myVector {
public:
myVector(/*some params*/);
~myVector();
// Some kind of overloading of operator []
// Some other code
private:
// private container array
double* vec;
// Some other code
};
int main ()
{
std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));
double val = sp[1];
return 0;
}
Комментарии:
1.
std::shared_ptr
может использоваться для хранения массива, а затем вы можете получить доступ к элементам черезoperator[]
. Если вshared_ptr
нем не хранится массив, как в вашем случае, вы вообще не можете полагаться на объявление оператора.2. Вы могли бы писать
(*sp)[1]
(разыменование, а затем доступ к индексу), если вы пишетеoperator[]
перегрузку. См . en.cppreference.com/w/cpp/language/operators особенно в отношении оператора подстрочного индекса массива.3. @NathanPierson Это было бы
(*sp)[1]
.4. FWIW, наличие указателя на «управляемый контейнер» обычно не то, что вам нужно.
5. @krisz Спасибо за исправление приоритета оператора
Ответ №1:
Вы можете объявить []
оператор для своего myVector
класса следующим образом (возвращая ссылку на элемент, чтобы у вас был доступ для чтения и записи):
doubleamp; operator [] (int i)
{
return vec[i];
}
Затем вы можете использовать этот оператор для объекта, на который указывает shared_ptr
при первом разыменовании. Вот выполняемый пример, где я добавил некоторый «фиктивный» код в конструктор, просто чтобы заставить его что-то делать:
#include <iostream>
#include <memory>
class myVector {
public:
myVector(/*some params*/) {
vec = new double[10];
for (int i = 0; i < 10; i) vec[i] = 3 * i;
}
~myVector() {
delete[] vec;
}
doubleamp; operator [] (int i) {
return vec[i];
}
private:
double* vec;
};
int main()
{
std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));
double val = (*sp)[6];
std::cout << val << std::endl;
(*sp)[4] = 312;
std::cout << (*sp)[4] << std::endl;
return 0;
}
Ответ №2:
Вы можете перегрузить оператор для класса следующим образом
double amp; operator []( size_t i )
{
return vec[i];
}
и
const double amp; operator []( size_t i ) const
{
return vec[i];
}
и назовите это как
std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));
//...
std::cout << ( *sp )[i] << 'n';
Комментарии:
1. @AdrianMole Они отличаются не только типами возвращаемых значений.
Ответ №3:
Я бы не стал этого делать в реальном приложении. Но просто для демонстрации, одна из возможностей достичь того, чего вы хотите (по крайней мере, технически), — это получить из std::shared_ptr и там объявить оператор индекса. Например:
#include <memory>
#include <vector>
using namespace std;
template <class T>
class myshared_ptr;
template <class T >
class myshared_ptr<vector<T>> : public shared_ptr<vector<T>>
{
public:
using elem_type = vector<T>;
using shared_ptr<elem_type>::shared_ptr;
using shared_ptr<elem_type>::operator*;
using shared_ptr<elem_type>::get;
typename elem_type::value_typeamp; operator[](size_t idx)
{
return (*get())[idx];
}
};
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!n";
auto p = myshared_ptr<vector<int>>(new vector<int>{1, 2, 3, 4});
cout << p[2] << endl;
return 0;
}