C ++: Как вы инициализируете членов внутренней структуры, используя список инициализации? - PullRequest
3 голосов
/ 22 июля 2011

Это действительно два вопроса, отмеченных ниже:

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

Есть ли способ инициализировать структуру в списке инициализатора без использования конструктора?

Будут ли эти помощники лучше подходить как внешний класс?

 
    class Foo {

    public:
    //...
        struct Bar {
            double mass;
            std::pair<double, double> gravMod;
            std::pair<double, double> position;
            std::pair<double, double> velocity;
            bool falling;
            Bar() : mass(0.0), gravMod(std::make_pair(0.0, 0.0)), position(std::make_pair(0.0, 0.0)), velocity(std::make_pair(0.0, 0.0)), falling(false) { };
            Bar(double _mass, std::pair<double, double> _gravMod, std::pair<double, double> _position, std::pair<double, double> _velocity, bool _falling) 
             : mass(_mass), gravMod(_gravMod), position(_position), velocity(_velocity), falling(_falling) { }
            Bar(const Bar& other) 
                : mass(other.mass), gravMod(other.gravMod), position(other.position), velocity(other.velocity), falling(other.falling) { }
        };

        struct Baz {
            std::pair<double, double> acceleration;
            std::pair<double, double> force;
            Baz() : acceleration(std::make_pair(0.0, 0.0)), force(std::make_pair(0.0, 0.0)) { }
            Baz(std::pair<double, double> _acceleration, std::pair<double, double> _force) 
                : acceleration(_acceleration), force(_force) { }
            Baz(const Baz& other) : acceleration(other.acceleration), force(other.force) { }
        };

    //...
    protected:
    //...
    private:
        Bar _currBar;
        Bar _prevBar;
        Baz _currBaz;
        Baz _prevBaz;
    };

 

EDIT

Примеры и связанные с ними ошибки:

 
Foo::Foo() : _currBar{0.0, std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0), false}, _currBaz{std::make_pair(0.0, 0.0), std::make_pair(0.0, 0.0)} { }
 

_currBar{ бросков: expected '('. Первые } бросков: expected';'.

 
Foo::Foo() : _currBar.mass(0.0), _currBar.gravMod(std::make_pair(0.0, 0.0)), _currBar.position(std::make_pair(0.0, 0.0)), _currBar.velocity(std::make_pair(0.0, 0.0)), _currBar.falling(false) { }
 

Первые _currBar. бросков: expected '('. Все _currBar. потом бросают Member 'Foo::_currBar' has already been initialized..

Ответы [ 3 ]

4 голосов
/ 22 июля 2011

В C ++ 03 нет способа инициализировать отдельные поля вложенного struct, а также нет способа инициализировать отдельные поля вложенного массива. В C ++ 0x (теперь, вероятно, C ++ 11) они ослабили это ограничение, и вы можете инициализировать вложенные struct s с помощью следующего синтаксиса:

Foo::Foo() : _currBar{fieldOneValue, fieldTwoValue, /* ... */, fieldNValue}, /* ... etc ... */

Добавление конструкторов к вашим вложенным struct s является тем временем вполне жизнеспособным вариантом, так как мы ожидаем, что больше компиляторов полностью поддержат эту функцию.

0 голосов
/ 22 июля 2011

В принципе, вы можете обойтись без конструкторов:

Foo::Foo(): _currBar(), _prevBar(), _currBaz(), _prevBaz() {}

Этот синтаксис инициализирует нулем объект без конструктора (устанавливает все поля в 0 / вызывает их конструктор по умолчанию).

Если вам нужен конструктор с параметрами, вы можете использовать вспомогательную функцию:

Bar make_bar(double mass, std::pair<double, double> gravMod, std::pair<double, double> position, std::pair<double, double> velocity, bool falling)
{
    Bar bar = { mass, gravMod, position, velocity, falling };
    return bar;
}

Foo::Foo(args...): _currBar(make_bar(args...)), ...

В любом случае вам не нужно добавлять конструктор копирования.Компилятор сгенерирует конструктор копирования, который будет делать именно это.

(Кстати, я бы, вероятно, не использовал бы std::pair, когда математический векторный класс был бы более подходящим. Я предполагаю, что такие вещи, как position могли былучше использовать свойства, называемые x и y over first и second.)

0 голосов
/ 22 июля 2011

Нет ничего плохого в подходе, который вы используете, если вы придерживаетесь следующего:

строго используется для передачи данных как одного объекта

При решении, использовать ли структуру или класс, нужно задать вопрос: существует ли инвариант для этого объекта? Инвариант, являющийся описанием того, что составляет действительное состояние для объекта. Если вы можете определить инвариант, то из этого следует, что вы также можете определить состояние недопустимое и что вам следует предоставлять доступ к внутренним переменным-членам только через функции-члены, чтобы обеспечить поддержание действительного состояния. Это лучше всего выполняется классом. Если, однако, любое старое государство будет делать; затем используйте структуру.

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

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