Почему мой перегруженный оператор кастинга не имеет доступа к закрытым членам?

#c #templates #casting #operator-overloading #private-members

#c #шаблоны #Кастинг #оператор-перегрузка #private-members

Вопрос:

Я пытаюсь реализовать перегруженный оператор приведения в моем шаблонном array2d классе, используя type T . Итак, я должен выполнить приведение из array2d<T> в новый array2d<E> .

Я могу выполнить приведение сам, но проблемы возникают, когда я пытаюсь установить приведенные данные в новый экземпляр array2d<E> . Компилятор сообщает мне, что оператор приведения не имеет доступа к закрытым элементам array2d

Вот где я нахожусь до сих пор (отредактировал несвязанный код для краткости)

array2d.h

 template<typename T>
class array2d {
private:
    // Member Variables
    T** data;
    size_t width, height;
public:
    // constructors, methods, etc...

    // Cast Operator
    template<typename E>
    operator array2d<E>() const;
};

// Other overloaded operators...

// Overloaded Casting Operator
template<typename T>
template<typename E>
array2d<T>::operator array2d<E>() const{
    // Create new instance
    array2d<E> castedArr(width, height);
    // Allocate memory for the casted data, then cast each element
    E** newData = new E*[castedArr.get_height()];

    for (size_t i = 0; i < castedArr.get_height(); i  ){
        newData[i] = new E[castedArr.get_width()];
        for (size_t j = 0; j < castedArr.get_width(); j  ){
            newData[i][j] = (E)data[i][j];
        }
    }
    // issue here, can't set data because it's private.
    castedArr.data = newData;

    delete [] newData;
    newData = nullptr;

    return castedArr;
}
  

main.cpp

 #include "array2d.h"

int main(int argc, char *argv[]) {
// Cast Operator
    // Create an array2d<T> of
    // width = 5
    // height = 5
    // fill all elements with 42.1
    array2d<double> x(5, 5, 42.1);

    // Create a new array exactly the same as
    // x, where x is casted to int
    array2d<int> y = (array2d<int>) x;

    return 0;
}
  

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

Почему это происходит и что я могу сделать, чтобы исправить это?

Комментарии:

1. Не связано: вы не хотите delete[] newData . Вы назначили эти данные в castedArr , который является новым владельцем и отвечает за удаление указателя, когда это будет сделано с ним.

2. Как я уже сказал @lubgr , если не использовать delete [] newData , деструктор нового экземпляра удостоверится, что он удален?

3. Это не решает вопрос, но этот вопрос касается оператора преобразования , а не оператора приведения . Приведение — это то, что вы пишете в своем исходном коде, чтобы сообщить компилятору выполнить преобразование. Многие преобразования могут быть выполнены без приведения.

Ответ №1:

При написании шаблона вы не указываете фактический тип, вы создаете предварительный вариант для разных типов. array2d<double> и array2d<int> — это разные типы, и по умолчанию два экземпляра двух разных классов не могут получить доступ к своим закрытым элементам.

Это можно исправить, объявляя каждый экземпляр array2d дружественного класса шаблона array2d :

 template<typename T>
class array2d {
    /* ... */

    template<class E> friend class array2d;

    /* ... */
};
  

В качестве примечания, я не совсем уверен, что

 delete [] newData;
  

это хорошая идея. Вы уничтожаете части ресурсов, которыми должен управлять новый array2d экземпляр. Если вы delete[] это повторите array2d::~array2d() , у вас будет неопределенное поведение.

Комментарии:

1. Большое спасибо, это было решение! Примечание к несвязанной стороне: если я этого не сделаю delete [] newData , позаботится ли об этом деструктор для этого экземпляра?

2. Вам определенно нужно реализовать деструктор самостоятельно. И вам нужно вручную delete[] как «внутреннее» хранилище для каждой строки, так и «внешнее». Просто идентичные вызовы new[] .