Как создать автоматические свойства (получить, установить) для Visual Studio 2008 C ++ - PullRequest
0 голосов
/ 26 октября 2009

Прочитав этот вопрос о генерации геттеров и сеттеров в Visual Studio и попробовав (несколько) описанные методы, я с треском провалился, выйдя за рамки обычного способа написания геттеров и сеттеров.

Хотя я осознаю концептуальное преимущество инкапсуляции (в данном случае это частные члены класса), написание 25 методов получения и установки - пустая трата времени и моего времени.

Почему 25? Кроме разницы в коэффициентах (около 2,5), я просто не знаю, в какой момент мне понадобится доступ к этой переменной в будущем. Полагаю, я мог бы написать функцию, которая возвращает все из них, и найти ту, которая мне нужна, но если я добавлю больше членов (часто делаю), то функция должна быть изменена во всем коде.

Мне нравится предложенная форма здесь для VS 2008:

string sName { get; set; }

Но он не скомпилируется в C ++. Это только для .NET и C # ?

Есть ли какой-нибудь аккуратный способ симулировать это в C ++?

Ответы [ 6 ]

5 голосов
/ 26 октября 2009

Спасибо @Dan за указание этого трюка в Microsoft Compiler (non-portable)

Вот путь:

struct person
{
    std::string m_name;
    void setName(const std::string& p_name)
    {
        m_name = p_name;
    }
    const std::string& getName() const
    {
        return m_name;
    }
    // Here is the name of the property and the get, set(put) functions
    __declspec(property(get = getName, put = setName)) std::string name;
};
int main()
{
    person p;

    p.name = "Hello World!"; // setName(...)
    std::cout << p.name;     // getName(...)
}

После создания member variables плюс getters и setters из этих member variables вы создаете property для каждой пары getter/setter. Вы можете называть это как хотите, потому что для этого свойства нужно указать метод получения и установки.


Просто для удовольствия:)

#define property(Type, Variable) private: Type Variable; \
      public: const Type##& get##Variable() const { return Variable; }; \
      void set##Variable(const Type& Variable##_) { Variable = Variable##_;}


 struct Test
 {
     property(int, x); property(int, y);
     property(std::string, text);
 };

int main()
{
    Test t;

    t.setx(10);
    t.sety(10);
    t.settext("Hello World at: ");
    std::cout << t.gettext() << " " << t.getx() << ", " << t.gety();
}
1 голос
/ 26 октября 2009

Почему 25? Хорошо, за исключением фактора преувеличения (около 2,5). Я просто не знаю, в какой момент мне понадобится доступ к этой одной переменной в будущем.

Вы понимаете, что это означает, что вы действительно не очень продумали свой дизайн. Вместо того, чтобы искать способы добавить свойства в C ++ (они не нужны). Должен ли я называть их «проперду», чтобы объяснить степень моей неприязни к ним?

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

Я понимаю, что это идет вразрез с «практическим правилом», согласно которому данные следует инкапсулировать в частном порядке с помощью методов получения и установки, чтобы в случае изменения структуры класса пользователи класса были защищены от этих изменений. Ну, к черту это. Сделайте это правильно с первого раза и тратьте меньше времени на суету об этом позже. Мой подход заключается в том, чтобы предоставить классу доступ пользователей к НИЧЕМУ, но к небольшому набору методов, и затем, если вам важно разрешить им доступ к некоторым частным значениям позже, вы можете добавить getter () позже. Когда я сказал «просто сделайте это публичным», следует понимать, что это означает «после исчерпывающего рассмотрения я знаю, что это абсолютно безопасно сделать публичным, потому что я полностью и полностью разработал свой класс с учетом всех вариантов использования».

Хорошо, теперь давайте ответим на этот ответ, потому что он отвечает на суть вопроса, а не на букву вопроса. Я ожидаю этого.

1 голос
/ 26 октября 2009

C ++ / CLI поддерживает автоматически реализованные свойства - он называет их «Тривиальные свойства» 1

1 голос
/ 26 октября 2009

Refactor! от DevExpress имеет довольно приятные функции для C ++, одна из которых - инкапсуляция таких полей, как C #.

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

float id;

плагин будет анимировать индикатор для отображения таких опций, как Encapsulate Field, который добавит:

property float Id
{
    void set(float value)
    {
        this->_id = value;
    }
    float get()
    {
        return this->_id;
    }
};

Если установка плагина действительно не ваша вещь, рассмотрите возможность использования макросов .

Лично я предпочитаю использовать макросы. Как только вы освоите их, они действительно просты. Я использовал оба, но мы застряли в Visual Studio 2003 (C #) до декабря, и плагины DevExpress не работают.

Я обычно использую макросы, чтобы начать в начале строки, нажать CTRL + SHIFT + R, чтобы начать запись. Затем введите, скопируйте и вставьте шаги, которые я хотел бы воссоздать. Когда закончите, нажмите CTRL + SHIFT + R, чтобы остановить запись. Затем CTRL + SHIFT + P воспроизведет последнюю запись. Вы также можете зайти в Macro Explorer и сохранить / отредактировать свои макросы. Затем вы можете просто дважды щелкнуть макрос, чтобы запустить его.

1 голос
/ 26 октября 2009

Автоматически реализованные свойства действительно являются функцией C #. Насколько я знаю, они не доступны в C ++. Я верю, что они появятся в VB 10, но я не знаю, будут ли они введены в C ++ / CLI.

Существует множество языковых функций, которые являются частью C #, но не C ++ (и наоборот, конечно). Вы не должны ожидать, что сможете использовать синтаксис одного языка на другом.

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

РЕДАКТИРОВАТЬ: Поскольку вы не хотите использовать управляемый код, вы даже не будете использовать C ++ / CLI, что делает его даже менее вероятным, что вы сможете использовать функции C #.

0 голосов
/ 26 октября 2009

Свойства возникли (я полагаю) в Delphi и перенесены на другие языки, особенно C #. В C ++ их нет встроенной поддержки (хотя я могу ошибаться в случае C ++. NET - в последнее время не проверял).

Я нашел эту статью об имитации свойств, которая выглядит сложной, но может решить вашу проблему. Кроме того, рассмотрите возможность использования C #, если это подходит вашему приложению - т.е. вы не пишете драйвер устройства. У него удивительная объектная модель и множество других преимуществ. Он не заменяет C ++ во всех аспектах, но отлично подходит для большинства приложений. Как сказал мой очень умный друг, используйте язык самого высокого уровня, который имеет смысл для вашего проекта.

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