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

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

Вот в чистом Си я писал

// comdefs.h
typedef struct
{
  u32 id   : 29;
  u32 ext  :  1;
#define CAN_IDDIR_RX    0
#define CAN_IDDIR_TX    1
  u32 dir  :  1;
#define CAN_IDTYPE_SVC  0
#define CAN_IDTYPE_WORK 1
  u32 type :  1;
}sCANID;

// nvm.c
static volatile const struct
{
  sCANID id[MAX_CANID_QNT];
  u32    crc;
}CANIDList __attribute__((section(".bss.nvm"), used)); // эта секция во Flash, если что

и все работало так, как мне нужно. Сейчас, когда переименовал nvm.c в nvm.cpp, ругается на определение CANIDList

Цитата

error: default initialization of an object of const type 'const volatile struct (anonymous struct at ...) without a user-provided default constructor


1. Где-то слышал, что C++ должен уметь компилировать чисто Си-шный код без каких-либо проблем. Тут я этого не вижу.
2. То, что в C++ структуры и классы, по сути, одно и то же, несколько смущает: раньше для меня структура была неким набором данных под одним общим наименованием, я мог их создавать как и где угодно, с какими мне угодно модификаторами и квалификаторами, а также копировать их из одного места в другое, не опасаясь за побочные эффекты и неявно выполняемый код. Сейчас же (со всеми этими конструкторами, конструкторами по-умолчанию, инициализаторами и т.д. не совсем понятно, структура ли это вообще или некая абстрактная фигня, с которой уже такие простейшие операции сделать не получится. ЧЗНХ? Я, конечно, C++ (как уже понятно) не так давно ковыряю, но черт его за ногу, Карл, это же структура! У меня была в чистом Си хорошая (на мой взгляд) привычка - не захламлять код там, где его можно не захламлять. В примере выше я не хочу создавать struct sCANIDList{...}; static volatile const struct sCANIDList CANIDList; а пишу сразу анонимную статическую константную структуру. Мне не нужно знать ее содержимое еще где-то, я не делаю определение глобальным. Оно для того у меня локальным в файле и сделано, т.к. используется только в нем. А значит не нужно делать сначала описание структуры, а потом ее определение. Но это было в Си. Так как же дела обстоят в C++ и как, по-хорошему, я должен написать? Сейчас мне пока что вырисовывается требование сначала написать определение структуры (чтобы можно было описать конструктор), а лишь потом объявить ее. Кошмар. Думалось мне, что плюсы банальностей не добавят.

P.S. Во, вот так работает (вроде даже правильно)

static volatile const struct sCANIDList
{
  sCANID id[MAX_CANID_QNT];
  u32    crc;
  
  sCANIDList() {}
}CANIDList __attribute__((section(".bss.nvm"), used));


Ну вот что мешало ему без определенным пользователем конструктора обойтись?

3. В CANIDList массив id[MAX_CANID_QNT] имеет тип sCANID, который является структурным типом, причем никаких конструкторов по-умолчанию в нем я не определял. Значит ли это, что перед выполнением конструктора по-умолчанию sCANIDList() сначала подряд будут вызваны неявные конструкторы по-умолчанию для всех объектов id? Так это же не эффективно! Равно как и вызывать пустой конструктор по-умолчанию sCANIDList(). Или компилятор, видя его тело пустым, не будет его вызывать физически?

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


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

15 minutes ago, Arlleex said:

Вот в чистом Си я писал

и все работало так, как мне нужно. Сейчас, когда переименовал nvm.c в nvm.cpp, ругается на определение CANIDList


1. Где-то слышал, что C++ должен уметь компилировать чисто Си-шный код без каких-либо проблем. Тут я этого не вижу.
2. То, что в C++ структуры и классы, по сути, одно и то же, несколько смущает: раньше для меня структура была неким набором данных под одним общим наименованием, я мог их создавать как и где угодно, с какими мне угодно модификаторами и квалификаторами

Вы, батенька, не с той стороны за язык С++ взялись.

По порядку:

В наше время С++ - это отдельный компилятор, который ОТЛИЧАЕТСЯ от просто Си компилятора. По стандарту. На одинаковые синтаксические конструкции они могут реагировать по-разному. Читать литературу по С++.

В ПРЕЖНИЕ времена, С++ реализовывался как набор макросов - приблуда к Си компилятору. Называлось "Си с классами" и действительно могло нативно компилировать чистый Си код. Теперь времена не те. Читать литературу по С++.

"То, что в C++ структуры и классы, по сути, одно и то же" - жестокое заблуждение, однако же  весьма типическое. Читать литературу по С++.

Три главных заклинания ООП не прозвучали ни в одном Вашем вопросе. Это значит, что Вы не понимаете СУТИ применяемого языка. Читать литературу по С++.

На пальцах - С++ появился тогда, когда объем исходного кода проектов на Си превысил десятки тысяч строк. И появилась НЕОБХОДИМОСТЬ в структуризации, ограничении областей видимости и тд. С ростом количества кода появилась потребность в повторном использовании кода - читай объектов, а также расширении и модификации их. Вот и повылезли на сцену Три главных заклинания ООП:

- представление программных сущностей объектами - классами. Читать литературу по С++. Класс - не структура! (Слышен громкий вой, помянул всуе...). Тут у меня программисты называют "классами"  любой *.hpp файл.

- класс представляет данные и методы манипулирования ими. Данные скрыты, доступ только через методы - это Инкапсуляция.

- класс можно развивать, наследуя от него. Это Наследование, code reuse.

- Одни и те же (по названию) методы работают с любыми данными - Полиморфизм. Читать литературу по С++ до просветления.

Все Ваши вопросы снимутся, как только Вы прочтете хоть одну правильную книгу. Не С++ за 10 дней.

Тогда программирование превратится в проектирование классов. Это работа Архитекта. А кодеры будут кодить эти классы для Вас. И да, кодеры - молодежь. А Архитект - по-прежнему бородатый пузан, живущий в мамином подвале.

Так выпьем за мирумир...

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


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

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

и все работало так, как мне нужно. Сейчас, когда переименовал nvm.c в nvm.cpp, ругается на определение CANIDList

Так:

struct sCANID {
  u32 id   : 29;
  u32 ext  :  1;
#define CAN_IDDIR_RX    0
#define CAN_IDDIR_TX    1
  u32 dir  :  1;
#define CAN_IDTYPE_SVC  0
#define CAN_IDTYPE_WORK 1
  u32 type :  1;
};

enum {MAX_CANID_QNT = 2};

__no_init struct {
  sCANID id[MAX_CANID_QNT];
  u32    crc;
} static volatile const CANIDList @ ".bss.nvm";

компилится молча и как c++ (IAR).

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


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

Уважаемый @Gorby!

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

Цитата

Класс - не структура!

Ну дык и отлично, но какого ж лешего я и для структур должен писать конструкторы, которые, вообще говоря, не для POD-объектов придуманы, а для объектов class-ов? С Ваших слов мой объект CANIDList не должен требовать никаких конструкторов, да и вообще не выполнять никакой C++-магии над этим объектом. Однако, это не так!

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


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

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

Ну дык и отлично, но какого ж лешего я и для структур должен писать конструкторы

У Вас он ругается на слово const. И вроде понятно почему. Уберите его - и ругаться перестанет.

PS: А вообще - class в c++ - это структура  :wink:   Только с public-членами по умолчанию.

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


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

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

Так... компилится молча и как .cpp (IAR).

Возможно, __no_init как-то влияет. У меня в Keil такого атрибута нет; он только в скрипте линкера есть. А поскольку компилятор ничего не знает об атрибутах области памяти, в которой разместится объект CANIDList, работает согласно Стандарту языка, видимо.

Цитата

У Вас он ругается на слово const. И вроде понятно почему...

Это да, однако ключевым словом const я
    а) хочу явно намекнуть о неизменности данных в этой структуре, дабы легким движением руки не записать туда ничего ненароком;
    б) при отсутствии атрибута размещения в определенной секции разместить CANIDList во Flash, а не в ОЗУ.

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


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

3 minutes ago, jcxz said:

PS: А вообще - class в c++ - это структура  :wink:   Только с public-членами по умолчанию.

Так-то да. Если к топору добавить соответствующие ингридиенты, то получится суп.

Это как бабушка с яй..и превращается в дедушку.

Всего добавок: конструктор, деструктор, This и правильный компилятор который это правильно поддерживает. Малая толика. Не герла Толяна, если что.

О, а наследовать от структуры можно?

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


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

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

О, а наследовать от структуры можно?

Ну как бы да, можно.

Цитата

Всего добавок: конструктор, деструктор, This...

А 'this' тут причем вообще? Он не содержится в классе/структуре, не занимает там память.
'this' неявно формируется при вызове метода, дабы понимать, над каким объектом работаем и только лишь всего.

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


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

13 минут назад, Gorby сказал:

О, а наследовать от структуры можно?

Конечно. Только наследование будет public по умолчанию, а не private, как для классов.

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


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

33 минуты назад, Gorby сказал:

Всего добавок: конструктор, деструктор, This

Перечитайте внимательнее:

43 минуты назад, jcxz сказал:

PS: А вообще - class в c++ - это структура  :wink:   Только с public-членами по умолчанию.

Соответственно - и конструктор и деструктор и this для struct имеются.

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

Читать литературу по С++

Вот именно! Последуйте своему совету.  :wink: 

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


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

Oh

3 hours ago, Gorby said:

 

- класс представляет данные и методы манипулирования ими. Данные скрыты, доступ только через методы - это Инкапсуляция.

Нет. Вторая половина - это сокрытие. Не является догмой ООП и есть ООП языки, где это отсутствует.

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

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


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

Это, конечно, эпик фэйл:sad: Кто-нибудь, кто достиг просветления в плюсах, скажите одну вещь: вам все нравится в этом языке? Я прочитал уйму всего уже по инициализации, но так и не нашел абсолютно конкретного ответа на вопрос: ну зачем комитет избавился от назначенной инициализации? Вернее, не то чтобы избавился, а сделал ее настолько кошмарно-неудобной, что, во-первых подгорает у сообществ (раз, два (комменты), ...), а во-вторых, внутри возникает стойкое ощущение того, что комитет сам себя в тупик загнал и понятия не имеет, как оттуда выбираться. У меня вот сейчас простая задача: расположить некую таблицу во Flash, а также еще одну, содержащую указатели на некоторые элементы первой + еще кое-какую информацию (строка имени). Причем "перекодировку" индексов я хочу делать "налету", попутно связывая индексы элементов одной и второй таблиц. Ну, короче, вот что

// вспомогательные структуры
typedef struct
{
  u32 id   : 29;
  u32 ext  :  1;
#define CAN_IDDIR_RX    0
#define CAN_IDDIR_TX    1
  u32 dir  :  1;
#define CAN_IDTYPE_SVC  0
#define CAN_IDTYPE_WORK 1
  u32 type :  1;
}sCANID;

typedef struct
{
  volatile const sCANID *id;
  const char            *name;
}sCANIFDesc;

// интересуемый кусок кода
static volatile const struct sCANIDTbl
{
  sCANID id[MAX_CANID_QNT];
  u32    crc;
  
  sCANIDTbl() {}
}CANIDTbl __attribute__((section(".bss.nvm"), used));

static const sCANIFDesc CANIFDesc[MAX_CANID_QNT] =
{
#define ITEM(dst, src, name) [dst] = {&CANIDTbl.id[src], name} // ну все, приехали: [n] = ... писать нельзя
  ITEM(0, 0, "XCAN RESERVED ID"),
  ITEM(2, 1, "ROOT:UHMIM:SVC RX ID"),
  ITEM(1, 2, "ROOT:UHMIM:SVC TX ID")
  ...
};


Т.е. смотрим ITEM(): индексы идут (и могут идти) не по порядку. Чуть позже я хотел создать #define-ны с осмысленными названиями индексов. Но, раз в C++ (по стандарту, что ли, получается?) нельзя выборочно инициализировать элементы массива (а также в любом синтаксически указанном порядке), то как C++-программисты вообще справляются? Тупо предполагая неявную индексацию инициализируемого массива? Заранее прошу не смахивать рукой а-ля "шо ты ноешь, сиди и на Си своем пиши", в таком случае лучше воздержитесь от ответа. Я хочу понять, откуда ноги растут у подобного рода языковых проблем и что с ними делать.

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


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

Что касается коммитета, они понимают, что гордиев узел надо разрубить. И тема об отказе от обратной совместимости не нова. Но при принятии новых стандартов не решаются на этот шаг.

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


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

То есть на текущий момент получается, что придется жертвовать синтаксическим удобством? Очень плохо:cray:

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


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

P. S. Задача выглядит надуманной: если это статическая константная структура, то определите еë полностью.

 

P. P. S непонятна задача полностью, вы показываете фрагмент. Но судя по тому, что я вижу, вы пытаетесь писать процедурный код, но на плюсах. Но зачем? Перестройте архитектуру под ООП.

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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