оператор перегрузки массива с шаблонами и указателями - PullRequest
0 голосов
/ 03 октября 2011

Следующий код компилируется (без предупреждений) как для clang ++ - 2.9, так и для g ++ - 4.6. Тем не менее, бинарные ошибки сегмента g ++, в то время как бинарный файл clang ++ работает как задумано.

Как правильно обращаться к членам данных шаблонного класса через указатели при перегрузке []?

Вот код:

#include <iostream>
template <typename T>
    class A {
    private:
    T val1;
    T val2;

    public:
    T& getVal1() { return val1; }
    void setVal1(T aVal) { val1 = aVal; }
    T& getVal2() { return val2; }
    void setVal2(T aVal) { val2 = aVal; }
};

template <typename T>
    class B {
    private:
    A<T>* aPtr;

    public:
    A<T>* getAPtr() { return aPtr; }
    T& operator[](const int& key) {
    if(key == 0) { T& res = getAPtr()->getVal1();
        return res; }
    else { T& res = getAPtr()->getVal2();
        return res; }
    }
};

int main()
{
    B<int> foo;
    foo[0] = 1;
    int x = foo[0];
    std::cout << foo[0] << " " << x << std::endl; // 1 1
}

Ответы [ 2 ]

0 голосов
/ 03 октября 2011

Если вы хотите вернуться по ref, то ваши функции A :: getValX () также должны возвращаться по ref, и ваша переменная res внутри оператора B :: также должна быть T & вместо T:

#include <iostream>
template <typename T>
    class A {
    private:
    T val1;
    T val2;

    public:
    T& getVal1() { return val1; }
    void setVal1(T aVal) { val1 = aVal; }
    T& getVal2() { return val2; }
    void setVal2(T aVal) { val2 = aVal; }
};

template <typename T>
    class B {
    private:
    A<T>* aPtr;

    public:
    A<T>* getAPtr() { return aPtr; }
    T& operator[](const int& key) {
        if(key == 0) { T& res = getAPtr()->getVal1();
            return res; }
        else { T& res = getAPtr()->getVal2();
            return res; }
    }
};

int main()
{
    B<int> foo;
    foo[0] = 1;
    int x = foo[0];
    std::cout << foo[0] << " " << x << std::endl; // 1 1
}

(Обратите внимание, что он все равно будет аварийно завершаться во время выполнения, поскольку aPtr нигде не инициализируется.)

Ваш исходный код возвращает ссылку на локальную переменную res, а не на A :: val1 / A:: val2, как вы, вероятно, намеревались.Если res - нереферентная переменная, то это будет простая копия значения val1 / val2, которая действительна только внутри области (в данном случае функции), где она была объявлена.Так что вам нужна ссылка здесь.

0 голосов
/ 03 октября 2011

Вы возвращаете ссылку на локальную переменную (res).Ссылка не будет действительной после возврата из оператора [].Это может быть перезаписано другими вещами.То, что действительно происходит, является неопределенным: именно поэтому компиляторам разрешается есть ваших детей или отращивать усы: неопределенное поведение

Возможно, вы захотите вернуться по значению.

Редактировать

Так как у вас есть установщик, вам не нужна ссылка: см. Решение в прямом эфире на http://ideone.com/oxslQ

Примечание: была другая проблема с aPtr, который не был инициализирован,Я предложил простой конструктор для этого._Вы можете инициализировать это из других источников ИЛИ вам нужно

  • присваивать и копировать конструкторы
  • или использовать shared_ptr для aPtr

.

#include <iostream>

template <typename T>
class A
{
private:
    T val1;
    T val2;

public:
    T getVal1()
    {
        return val1;
    }
    void setVal1(T aVal)
    {
        val1 = aVal;
    }
    T getVal2()
    {
        return val2;
    }
    void setVal2(T aVal)
    {
        val2 = aVal;
    }
};

template <typename T>
class B
{
private:
    A<T>* aPtr;
    B(const B&);            // TODO , disallow for now
    B& operator=(const B&); // TODO , disallow for now

public:
    B() : aPtr(new A<T>()) {}
    ~B() { delete aPtr; }

    A<T>* getAPtr()
    {
        return aPtr;
    }
    T operator[](const int& key)
    {
        if(key == 0)
        {
            T res = getAPtr()->getVal1();
            return res;
        }
        else
        {
            T res = getAPtr()->getVal2();
            return res;
        }
    }
};

int main()
{
    B<int> foo;
    foo.getAPtr()->setVal1(1);
    int x = foo[0];
    std::cout << foo[0] << " " << x << std::endl; // 1 1
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...