Перейти к содержанию
    

Плавный переход C -> C++ под МК

2 hours ago, EdgeAligned said:

За всё время - только namespace, class/struct в самом базовом понятии и немного шаблонов.

Вероятно, сказывается специфика образования. Возможно, что ТС изначально учился программировать (без обид) на Васике, поэтому он не чувствует естественности ООП. Кроме того, не всем читали курс системного анализа с его декомпозицией цели и прочим.

Возможно мне показалось, но многие отвечающие тут, так же как и я не задумывались о многих недостатках С++, пока не прочитали вопрос или какую-нибудь сентенцию об этом недостатке/недоработке. Видимо, тут как в сексе, когда видишь желанное тело, не замечая новой морщинки на нём.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

37 минут назад, Forger сказал:

подключаю внутри CPP,

но при этом есть косяк с выносом шаблонных методов класса в .cpp. 
Например я такой подход применяю для записи в регистры BSRR/BRR, когда записываемое значение передается в параметра шаблона. В этом случае одиночный пин дергается максимально быстро, потому что параметр шаблона - константа.
И вот для этого случая у меня не получилось вынести шаблонный метод вне класса в файл .cpp, хотя в .hpp выносится без проблем. Возможно, есть какой-то обходной костыль на этот счет, не знаю, но оставил как есть и смирился, это не столь уж принципиально, на работу не влияет.

39 минут назад, tonyk_av сказал:

сказывается специфика образования

А у меня вообще нет профильного образования в этой сфере 🙂 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

35 minutes ago, EdgeAligned said:

но оставил как есть и смирился, это не столь уж принципиально, на работу не влияет.

аналогично )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компонент (класс) дает метод, в котором есть параметром некий const Idglobal::TIdBytes AData.

Лезу смотрю кто такой: вижу typedef System::DynamicArray<System::Byte> TIdBytes. Ок, конкретизировали шаблон для псевдонима. Лезу дальше.

/////////////////////////////////////////////////////////////////////////////
  // DynamicArray
  // ============
  // Template providing Delphi style Dynamic Array support in C++
  /////////////////////////////////////////////////////////////////////////////
  template<class T> class RTL_DELPHIRETURN DynamicArray
  {
  public:
    DynamicArray();
#if defined(SYSDYN_HAS_CXX11)
    DynamicArray(std::initializer_list<T> il);
    template <class... Types>
    DynamicArray(const T &t, Types && ...values);
#else
    DynamicArray(const T &t0,  const T &t1);
    DynamicArray(const T &t0,  const T &t1,  const T &t2);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13, const T &t14);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13, const T &t14, const T &t15);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13, const T &t14, const T &t15,
                 const T &t16);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13, const T &t14, const T &t15,
                 const T &t16, const T &t17);
    DynamicArray(const T &t0,  const T &t1,  const T &t2,  const T &t3,
                 const T &t4,  const T &t5,  const T &t6,  const T &t7,
                 const T &t8,  const T &t9,  const T &t10, const T &t11,
                 const T &t12, const T &t13, const T &t14, const T &t15,
                 const T &t16, const T &t17, const T &t18);
#endif /* defined(SYSDYN_HAS_CXX11) */
    template <size_t SIZE>
    DynamicArray(T(&array)[SIZE]);
    ~DynamicArray();

    // Construct from another DynArray
    DynamicArray(const DynamicArray<T>& src);

    // Assign data from another DynArray
    DynamicArray& operator=(const DynamicArray<T>& src);

    // Subscript operator to access data
    T& operator[](DynArrInt index);
    const T& operator[](DynArrInt index) const;

    // Comparison (NOTE: only pointer is compared)
    bool operator == (const DynamicArray<T> &other) const;

    // Make copy of data (non-refcounted)
    DynamicArray<T> Copy() const;
    void            Copy(DynamicArray<T> &dst) const;
    DynamicArray<T> CopyRange(DynArrInt startIndex, DynArrInt count) const;
    void            CopyRange(DynamicArray<T> &dst, DynArrInt startIndex, 
                                                    DynArrInt count) const;

    // High and low bounds of DynArray
    DynArrInt       get_high() const;
    DynArrInt       get_low() const;

    // Set/get length of DynArray
    DynArrInt       get_length() const;
    void            set_length(DynArrInt l);

    int             get_refCount() const;

    // Properties
    __property DynArrInt Length = {read=get_length, write=set_length};
    __property DynArrInt High   = {read=get_high};
    __property DynArrInt Low    = {read=get_low};

    __property int RefCount     = {read=get_refCount};

    // Returns number of dimensions of dynamic array
    // NOTE: Used with 'GetDimensions' template functions above.
    //       If T happens to be another DynamicArray, the compiler
    //       resolves the call to the first version of GetDimensions.
    //       Otherwise, it defaults to the second version.
    //
    static DynArrInt DimCount()
    {
      return 1 + GetDimensions(*((T*)(0)));
    }

#if !defined(NO_SYSDYN_ITERATOR)
    // Iterators
    class iterator;
    iterator begin();
    iterator end();
#endif

  protected:
    void            IncRefCount();
    void            DecRefCount();
    static T*       AllocData(DynArrInt count);
    void            SetData(T* t);
    void            FreeData();

  private:
    T*              Data;
    TDynArrayRec& GetRec() 
    { return reinterpret_cast<TDynArrayRec*>(Data)[-1]; }
    const TDynArrayRec& GetRec() const
    { return reinterpret_cast<const TDynArrayRec*>(Data)[-1]; }
#if defined(SYSDYN_HAS_CXX11)
    void PushBackElement(DynArrInt index, const T &t);
    template <class... Types>
    void PushBackElement(DynArrInt index, const T &t, Types && ...values);
#endif /* defined(SYSDYN_HAS_CXX11) */
  };


А теперь да, скажите, что в это дерьмо не нужно погрузиться в скафандре полностью, раскурив и поняв что тут написано и как это применять!

Вот я даже сходу понятия не имею, как мне, б#%ть, вызвать первоначальный метод:biggrin: Каеф.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, Arlleex said:
RTL_DELPHIRETURN 

Фраза "DELPHI" - уже с осторожностью надо к этому относиться. Внутрь конечно не надо лазить просто так. А в чем собственно вопрос/проблема?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

  

3 часа назад, Arlleex сказал:

как мне, б#%ть, вызвать первоначальный метод

Просто создать объект этого класса и использовать перегрузку оператора индексирования [] для доступа к элементам массива. По желанию, использовать итераторы.

Вот исчо раз повторюсь, что пробелы в изучении будут давать о себе знать в последствии. Вот что мешало вначале на примитивных примерах типа А+Б разобраться в основах, а потом уже применять инструментарий на практике? Три года для этого вполне бы хватило, и не было бы сейчас такого, когда на в принципе то базовый набор методов вы смотрите как на новые ворота. Ведь тут в классе не записано ничего сверхфантастичного, и если откинуть подробности, то набор предстанет в простом виде - конструкторы с параметрами, перегрузки операторов, итераторы и внутренние поля, хранящие соппсна внутреннюю инфу.

В принципе, вот пример обычного состава подобного класса массива (статического) :

class A {
public:
	/* Конструктор без параметров (не обязателен) */
	A(): buf(nullptr), size(0) { }

	/* Конструктор с параметрами */
	A(int size): buf(new int[size]), size(size) { }

	/* Конструктор копирования */
	A(const A &other);

	/* Конструктор перемещения */
	A(A &&other);

	/* Деструктор */
	~A();

	/* Оператор присваивания */
	A& operator =(const A& other);

	/* Оператор перемещения */
	A& operator =(A &&other);

	/* Оператор индексирования */
	int& operator [](int index);

	/* Операторы сравнения */
	bool operator ==(const A& other);
	bool operator !=(const A& other);

	/* геттер */
	int getSize() const
	{
		return size;
	}

private:
	int *buf;
	int size;
};

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

И вот как сия замута должна применяться:

A a1(7), a2(10), a3(a2);
if(a1 != a2)
{
	a1 = a2;
}

a1[5] = 100;
int s = a3[4];

 

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, EdgeAligned сказал:

Если получше разбираться в основах классов, в конструкторах и перегрузках операторов, тут в принципе не так уж и сложно, и можно понять...

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

Вот скажите мне, в какой такой строчке мне должно стать очевидным, что запись вида obj.Length = 0 освобождает дин. память? Лишь в документации написано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

А теперь да, скажите, что в это дерьмо не нужно погрузиться в скафандре полностью, раскурив и поняв что тут написано и как это применять!

Вот я даже сходу понятия не имею, как мне, б#%ть, вызвать первоначальный метод:biggrin: Каеф.

Насколько я понял, это заголовочный файл от System.DynamicArray (из RAD Studio, который давным-давно был C++ Builder). Это очень навороченный тип, с подсчётом ссылок, итераторами, свойствами (нестандартное расширение языка, емнимс), и прочим подобным. Понятное дело, что выглядит мощно 🙂

Кучу конструкторов с разным числом параметров можно выкинуть, оставив только ветку для c++11. И так далее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, если известно, тогда какие проблемы разобрать написанное то? 🙂

1 минуту назад, Arlleex сказал:

в какой такой строчке мне должно стать очевидным, что запись вида obj.Length = 0 освобождает дин. память?

Так это не к языку претензия, а к кодописателю. А документация на то и предусмотрена, чтобы прояснять все эти моменты. Ну и вполне логично, что если длина массива становится равной нулю, то динамически выделенную память нужно освободить полностью, во избежание утечки памяти.
С динамическим выделением памяти есть отдельная баго-фича, такая, как фрагментация памяти. Про это тут мы ранее уже писали.

9 минут назад, Arlleex сказал:

на изучение интерфейса класса не должно тратиться много времени.

"Много" - понятие неопределенное 🙂 А вообще, если кодописатели уважают других последователей, то они снабжают свой код документацией, например в стиле Doxygen. Эта штука весьма удобна тем, что генерирует html-описалово, куда можно поместить все подробности и примеры использования, и даже исходные тексты кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 минут назад, Arlleex сказал:

Вот скажите мне, в какой такой строчке мне должно стать очевидным, что запись вида obj.Length = 0 освобождает дин. память? Лишь в документации написано.

А почему это должно стать очевидным? Для std::shared_ptr, например, тоже есть обширная документация, без чтения которой его сложно использовать правильно. И это нормально, на мой взгляд.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 минут назад, AHTOXA сказал:

Насколько я понял, это заголовочный файл от System.DynamicArray (из RAD Studio, который давным-давно был C++ Builder). Это очень навороченный тип, с подсчётом ссылок, итераторами, свойствами (нестандартное расширение языка, емнимс), и прочим подобным. Понятное дело, что выглядит мощно 🙂

Кучу конструкторов с разным числом параметров можно выкинуть, оставив только ветку для c++11. И так далее.

Да, он самый))

А вот в "чистом" C++ есть что-то типа этого?

__property DynArrInt Length = {read=get_length, write=set_length};


Действительно иногда красивше напрямую писать/читать член класса, а вместо этого будет вызываться соответствующий метод?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 минут назад, Arlleex сказал:

А вот в "чистом" C++ есть что-то типа этого?

Нет, это их нестандартное языковое расширение. Чтобы с delphi-кодом взаимодействовать.

20 минут назад, Arlleex сказал:

Действительно иногда красивше напрямую писать/читать член класса, а вместо этого будет вызываться соответствующий метод?

Я в последнее время не люблю неявных вещей. Пишешь obj.length=0, вроде бы простое присвоение. А оказывается, что там под капотом куча побочных действий происходит. Лучше уж obj.setLength(0). Не особо длиннее, но зато явно видно вызов функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 часов назад, Arlleex сказал:

А теперь да, скажите, что в это дерьмо не нужно погрузиться

написать дерьмо можно и на си, на %ПОДСТАВЬ_ИМЯ_ЯЗЫКА%. Этот код борланд-стаил. Борланд славится тем, что не придерживается строгому стандарту, а пытается стандарт под себя прогнуть. Даже в народе ходит выражение "Есть язык С++, а есть язык Borland-C++".

 

На с++ такой код

classA.size = 100;

Очевидно, что у classA есть публичный член size. В Borland-C++

Tlabel label;
label.text = "Hello word"

с точки зрения c++ text - это публичный указатель. Но в борланде за text через __property cпрятан сеттер типа Tlabel::setText(consr char *str).

Школата и неокрепшие умы начинают пробовать свои силы в с++ и пробуют писать форточки на народном Borland-C++. Программисты МК, закоренелые сишники, пишут утилитки для отладки своего железа с ПК (до сих пор многие сидят на  Borland-C++ 6).

борланд предлагает class.text = "hello". Они видят, что text в паблике и  приучаются к этому и потом пишут свой код на с++, без сетеров/гетеров, всё в паблике и не парятся. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...