Членские псевдонимы переменной C++?

Измените следующий код, чтобы передать пустой объект, если ноль

let display = this.state.giftContainer 
&& this.state.giftContainer === true 
?(<GiftBoxAnimation gift={this.state.gift1 || {}}/>)
:(null);
12
задан mcccclean 30 January 2009 в 05:50
поделиться

11 ответов

То, что я сделал бы, делают средства доступа:

struct Vertex {
    float& r() { return values[0]; }
    float& g() { return values[1]; }
    float& b() { return values[2]; }

    float& x() { return values[0]; }
    float& y() { return values[1]; }
    float& z() { return values[2]; }

    float  operator [] (unsigned i) const { return this->values_[i]; }
    float& operator [] (unsigned i)       { return this->values_[i]; }
    operator float*() const { return this->values_; }

private:
    float[3] values_;
}
22
ответ дан 2 December 2019 в 02:58
поделиться

Просто предупреждение об использовании ссылочных участников, указывающих для оценки участников. Необходимо определить конструктора копии (и возможно также оператор присваивания), если Вы когда-либо копируете такой объект (как передача он значением). Конструктор копии по умолчанию оставит Вас с копией, ссылочные участники которой указывают членам значения исходного объекта, не тех нового объекта. Это - конечно, не что-то, что Вы хотите.

Рассмотрение Вы также заканчиваете с большими объектами, как уже говорилось, я думаю с помощью методов доступа, должен быть предпочтен по ссылочным участникам.

0
ответ дан 2 December 2019 в 02:58
поделиться

У меня есть шаблон и два Векторных класса ниже, один сумасшедший, один нормальный. Шаблон реализует простое, зафиксированное во время компиляции массив значений. Это разработано для разделения на подклассы и использует защищенную переменную типа массив для ухода от Вас имеющий необходимость перейти через обручи для доступа к массиву. (Некоторым людям не мог бы понравиться такой дизайн. Я говорю, если Ваши подклассы называют Ваши перегруженные операторы, связь могла бы быть хорошей идеей.)

Сумасшедший класс позволяет Вам иметь членские переменные, названные x, y, z, и он действует как массив вызовов к glGetFloatV. Нормальный просто имеет функции средства доступа x (), y (), z () и все еще работает с glGetFloatV. Можно использовать любой класс в качестве основания для других объектов вектора, которые что Вы могли бы передать библиотеке OpenGL. Хотя классы ниже характерны для точек, можно, очевидно, просто сделать поиск/замену для превращения их в цвет rgb классы.

Сумасшедший класс является сумасшедшим, потому что стоимость синтаксического сахара vec.x вместо vec.x () является 3 ссылочными переменными. Это могло поднять много пространства в крупном приложении. Используйте более простую нормальную версию.

template <typename T, int N>
class FixedVector {
protected:
    T arr[N];
public:
    FixedVector();

    FixedVector(const T* a) {
        for (int i = 0; i < N; ++i) {
            arr[i] = a[i];
        }
    }

    FixedVector(const T& other) {
        for (int i = 0; i < N; ++i) {
            arr[i] = other.arr[i];
        }
    }

    FixedVector& operator=(const T& other) {
        for (int i = 0; i < N; ++i) {
            arr[i] = other.arr[i];
        }
        return *this;
    }

    T* operator&() { return arr; }
    const T* operator&() const { return arr; }

    T& operator[](int ofs) { 
        assert(ofs >= 0 && ofs < N);
        return arr[ofs];
    }
    const T& operator[](int ofs) const { 
        assert(ofs >= 0 && ofs < N);
        return arr[ofs];
    }
};

class CrazyPoint :  public FixedVector<float, 3> {
public:
    float &x, &y, &z;

    CrazyPoint()
      : x(arr[0]), y(arr[1]), z(arr[2])
    { arr[0] = arr[1] = arr[2] = 0.0; }

    CrazyPoint(const float* a)
      : x(arr[0]), y(arr[1]), z(arr[2])
    {
        arr[0] = a[0];
        arr[1] = a[1];
        arr[2] = a[2];
    }

    CrazyPoint(float a, float b, float c) 
      : x(a), y(b), z(c)
    {
        arr[0] = a;
        arr[1] = b;
        arr[2] = c;
    }
};

class SanePoint : public FixedVector<float, 3> {
public:
    float& x() { return arr[0]; }
    float& y() { return arr[1]; }
    float& z() { return arr[2]; }

    SanePoint() { arr[0] = arr[1] = arr[2] = 0.0; }
    SanePoint(float a, float b, float c) 
    {
        arr[0] = a;
        arr[1] = b;
        arr[2] = c;
    }
};

// usage
SanePoint normal;
glGetFloatV(GL_CURRENT_NORMAL, &normal);
0
ответ дан 2 December 2019 в 02:58
поделиться

Можно попытаться добавить ссылки на переменные, как это:

struct test {
        float x, y, z;
        float &r, &g, &b;

        test() : r(x), g(y), b(z) {}
    };

Но Ваша структура становится больше (от 12 байтов до 40 байтов).

Для использования [] на нем используйте перегрузку оператора [], как упомянуто прежде.

0
ответ дан 2 December 2019 в 02:58
поделиться

Плохая идея, по-моему, по крайней мере, для данного примера: оборотная сторона - то, что для примерно любого решения этого Вы, вероятно, собираетесь быть способными свободно присвоить "rgb" экземпляры "xyz" экземплярам, который, вероятно, редко разумен или корректен. т.е. Вы рискуете бросать некоторую полезную безопасность типов.

Лично, для примера Вы даете, я разделил бы на подклассы rgb и типы xyz от основы boost::array<float,3> или подобный. Таким образом, они оба наследовали оператор [], могут быть переданы функциям, ожидающим массивы, и переданы с большей безопасностью типов вещам, ожидающим цвета/координаты. Это часто, Вы хотите рассматривать xyz или rgb как массив, но редкий Вы хотите рассматривать xyz как rgb или наоборот. (rgb массив ISA: хорошо. xyz массив ISA: хорошо. rgb ISA xyz????Я так не думаю!)

Конечно, это означает доступ к x, y, z, и r, g, b должен быть средством доступа (передающий соответствующему operator[](...) ) вместо прямо к участнику. (Вам были бы нужны свойства C# для этого).

1
ответ дан 2 December 2019 в 02:58
поделиться

Я не уверен, понял ли я вопрос правильно. Но похоже, что необходимо перегрузить оператор [] для обеспечения массива как доступ к структуре/классу. Посмотрите пример, упомянутый здесь: перегрузка Оператора

2
ответ дан 2 December 2019 в 02:58
поделиться

Ссылки?

template<typename T>
struct vertex {
    vertex() :
        r(data[0]), g(data[1]), b(data[2]),
        x(data[0]), y(data[1]), z(data[2])
    {
    }

    T *operator *() {
        return data;
    }

    const T *operator *() const {
        return data;
    }

    T data[3];
    T &r, &g, &b;
    T &x, &y, &z;
};
3
ответ дан 2 December 2019 в 02:58
поделиться

Использовать объединение?

union vertex
{
    struct { float x, y, z; };
    struct { float r, g, b; };
    float arr[3];
};

Я не рекомендовал бы это - это приведет к беспорядку.


Добавленный:

Как отмечено Adrian в его ответе, это объединение с анонимными участниками структуры не поддерживается ISO C++. Это работает в GNU G ++ (с жалобами на то, чтобы не быть поддерживаемым, когда Вы включаете'-Wall -ansi -pedantic'). Это напоминает о пред пред стандарт C дни (pre-K&R 1-й Edn), когда имена элементов структуры должны были быть уникальными через все структуры, и Вы могли использовать законтрактованные нотации для получения до смещения в структуре, и Вы могли использовать имена элемента от других типов структуры - форма анархии. К тому времени, когда я начал использовать C (давным-давно, но post-K&R1), который уже был историческим использованием.

Нотация, показанная с анонимными членами профсоюза (для этих двух структур), поддерживается C11 (ISO/IEC 9899:2011), но не более ранними версиями стандарта C. Разделите 9.5 из ISO/IEC 14882:2011 (C++ 11) предусматривает анонимные объединения, но GNU g++ (4.9.1) не принимает код, показанный с -pedantic, идентификация"warning: ISO C++ prohibits anonymous structs [-Wpedantic]".

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


Вопрос был поставлен:

Три (x-y-z, r-g-b и массив) не обязательно выравниваются.

Это - объединение с тремя элементами; эти три элемента запускаются в том же адресе. Первые два являются структурами, содержащими 3 значения плавающих. Нет никакого наследования и нет никаких виртуальных функций для предоставления различных разметок и т.д. Структуры будут размечены с этими тремя непрерывными элементами (на практике, даже если стандарт разрешит дополнять). Массив также запускается в том же адресе, и подвергающийся 'никакому дополнению' в структурах, элементы перекрывают эти две структуры. Я действительно не вижу, что была бы проблема.

12
ответ дан 2 December 2019 в 02:58
поделиться

Можно получить это с объединением, как другие упомянули. Перегрузка цвета и положения на ту же структуру как это не может быть хорошей идеей (например, добавляя, что два цвета обычно означают, что Вы хотите насыщать к 1,0, тогда как добавление векторов происходит линейно), но накладывание плавания [] сверху их как этот прекрасно подходит и хорошо принятое средство чередующихся данных с GL/DirectX/и т.д.

Я рекомендую постараться не обращаться к тому же участнику различными псевдонимами в том же функциональном объеме, тем не менее, потому что это будет управлять Вами в противный аппаратный останов, названный хранилищем хита загрузки. В частности, избегайте этого, если Вы можете:

vector foo; 
foo.x = 1.0f;
return foo[0] + foo[1];
3
ответ дан 2 December 2019 в 02:58
поделиться

Я предполагаю, что можно сделать некоторое макро-волшебство получить то, что Вы хотите. Но это будет выглядеть ужасным. Почему Вы хотите использовать ту же структуру, вершину для 3 различных типов? Почему Вы не можете определить класс для цвета? Также имейте в виду, что вершина и цвет не то же. Если Вы изменяете что-то на вершину, которая будет влиять на цвет также, если у Вас будет тот же класс для обоих.

2
ответ дан 2 December 2019 в 02:58
поделиться

Неназванными вложенными структурами в объединении не является стандартный C++. Это, однако, должно работать:

struct Vertex
{
private:
   typedef float Vertex::* const vert[3];
   static const vert v;

public:
   typedef size_t size_type;
   float x, y, z;

   const float& operator[](size_type i) const {
      return this->*v[i];
   }

   float& operator[](size_type i) {
      return this->*v[i];
   }

};

const Vertex::vert Vertex::v = {&Vertex::x, &Vertex::y, &Vertex::z};

Править: Немного больше информации. Структура использует массив 3 pointer-to-data-members для доступа к данным в перегруженном [] операторы.

Строка "определение типа пускает в ход Вершину::*, константа vert" означает, что vert является указателем на члена плавающего структуры Вершины. [3] средства, что это - массив 3 из них. В перегруженном операторе [], индексируется этот массив, и pointer-to-data-member разыменовывается и возвращенное значение.

Кроме того, этот метод должен работать независимо от упаковки проблем - компилятор является бесплатным заполнить структуру Вершины однако, этому нравится, и это будет все еще работать просто великолепно. Анонимное объединение столкнется с проблемами, если плавания будут упакованы по-другому.

13
ответ дан 2 December 2019 в 02:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: