Установить указатель на значение плюс отдельное значение - PullRequest
1 голос
/ 07 марта 2012

Можно ли установить указатель на значение, но с небольшим смещением.

Что-то вроде:

m_NewPosition = &m_Position + Vector3(0,0,10);

Таким образом, значение NewPosition - это фактическая позиция плюс 10 передних.

Использование c ++.

Ответы [ 5 ]

3 голосов
/ 07 марта 2012

Вы можете использовать смещения только с указателями, если указатель указывает на массив.

Так что, если у вас есть char arr[10]; и вы что-то его наполняете, тогда вы можете сделать char *p = arr + calc_offset();, если вы не выходите за пределы массива.

из стандарта C ++:

Если операнд-указатель и результат указывают на элементы тот же объект массива, или один после последнего элемента объекта массива, оценка не должна приводить к переполнению; в противном случае, поведение не определено.

1 голос
/ 07 марта 2012

Кажется странным, что вы захотите взять адрес m_Position и добавить к нему вектор.Возможно, это помогло бы нам больше, если бы мы знали, где находятся ваши указатели.Мы не знаем типов m_NewPosition или m_Position, поэтому трудно помочь.Однако кажется маловероятным, что вам вообще понадобятся указатели.

Я предполагаю, что эти две переменные имеют тип Position, который является классом, который выглядит примерно так:

Если это так, и вы хотите применить дополнение к этой позиции с Vector3 в качестве второго операнда, то вам нужно перегрузить operator+ для этого класса.Для этого сделайте что-то вроде этого:

class Position {
 public:
  Position(int x, int y, int z) : x(x), y(y), z(z) { }
  Position operator+(const Vector3& vector) {
    return Position(x + vector.x, y + vector.y, z + vector.z);
  }
 private:
  int x;
  int y;
  int z;
}

Как видите, метод operator+ позволяет добавить вектор к этой позиции.Теперь вы просто сделаете:

m_NewPosition = m_Position + Vector3(0,0,10);

В этом примере, однако, m_Position не изменится.Он останется таким же, каким был всегда.Вызов operator+ просто вернет новый Position с обновленными компонентами.Если вы хотите обновить m_Position, то вы, вероятно, хотите перегрузить operator+=.

1 голос
/ 07 марта 2012

Звучит так, как будто вы на самом деле ищете функцию, результат которой зависит от значения m_Position. По префиксу m_ я понимаю, что это оба участника. Если m_Position + Vector3(0,0,10) является константой, это может быть просто обычная функция-член:

Vector3 m_NewPosition() const {
    return m_Position + Vector(0,0,10);
}

Но если вам нужна возможность изменить функцию, вы можете использовать std::function<Vector3(void)> и назначить ее следующим образом:

m_NewPosition = [&m_Position]() { return m_Position + Vector3(0,0,10); };

Вот простой пример, но с целыми числами вместо векторов.

#include <iostream>
#include <functional>

struct Foo
{
    Foo()
        :X(0)
    {
        NewX = [&X]() { return X + 10; };
    }

    int X;
    std::function<int(void)> NewX;
};

int main()
{
    Foo f;
    for (f.X=0; f.X<10; ++f.X)
    {
        std::cout << f.NewX() << '\n';
    }
}

И онлайн-демонстрация, чтобы вы могли просмотреть результат: http://ideone.com/XTwE7


Другой вариант - убедиться, что и m_Position, и m_NewPosition являются закрытыми, и никогда не изменять их напрямую, а только через функции доступа, например,

class Foo
{
public:
    void IncrementPosition(const Vector3 & rhs)
    {
        m_Position += rhs;
        m_NewPosition = m_Position + Vector3(0,0,10);
    }
private:
    Vector3 m_Position, m_NewPosition;
};
1 голос
/ 07 марта 2012

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

0 голосов
/ 07 марта 2012

Если я правильно понимаю, вы хотите, чтобы m_NewPosition всегда было равно m_Position плюс некоторое смещение в пространстве, даже когда оно модифицируется (что-то вроде реактивного программирования ).Это не достижимо, как вы пытались это сделать, вы, вероятно, должны найти хорошую ссылку на указатели.Тем не менее, в вашем распоряжении есть несколько решений.

Первое - использовать функцию / метод, , как @Benjamin Lindley предложил : поскольку NewPosition является вычисленным значением, оно делаетсмысл вычислять его в функции:

class Character
{
  public:
    Vector3 getPosition() const
    {
        return m_Position;
    }

    Vector3 getNewPosition() const
    {
        return getPosition() + Vector3(0, 0, 10);
    }

  private:
    Vector3 m_Position;
};

Это весь смысл инкапсуляции, означающий скрытие внутренних частей вашего объекта: «видимые» свойства вашего объекта должны быть доступны только через функции-члены (методы), позволяя вам изменить способ их хранения или вычислить их «на лету», например m_NewPosition в вашем примере.

Другое решение, более сложное (и, вероятно, не подходящее в вашем случае),это написать новый класс, который представляет относительную позицию:

class RelativePosition
{
  public:
    RelativePosition(Vector3 const & origin, Vector3 const & offset)
      : m_Origin(origin), m_Offset(offset)
    {}

    Vector3 getAbsolutePosition() const
    {
        return m_Origin + m_Offset;
    }

  private:
    Vector3 const & m_Origin;
    Vector3 m_offset;
};

Обратите внимание, как RelativePosition хранит ссылку на его происхождение, а не копию;благодаря этому, если источник изменен (т. е. перемещен), относительная позиция будет отражать это изменение.

Теперь вы можете использовать экземпляр этого класса для представления m_newPosition, который действительно является относительной позицией(относительно m_Position, со смещением `Vector3 (0, 0, 10)).Однако, как я уже говорил ранее, я думаю, что это решение, вероятно, излишне для вашего случая;вам, вероятно, следует придерживаться предыдущего подхода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...