Есть иерархия классов. Каждый класс имеет список имен ему нужных параметров, которые потом как-то используются как внутри класса так и извне его. Этот список постоянный для каждого класса. Причем в списке класса потомка присутствует весь список от базового класса. Написал решение. Упрощенный вариант см. ниже. Но можно ли как-то попроще/поизящней? Много копи-паста и следовательно возможностей ошибок.
Используется VS 2017 с ключом /c++17. Списки не очень большие — максимум несколько десятков элементов. Много классов имеют пустой собственный список (т.е. только от базового класса).
S>int main()
S>{
S> B * d1 = new D1;
S> B * d2 = new D2;
S>}
S>
Простите, что не по теме вашего вопроса. Но.
По работе временами приходится заглядывать в дебри чужого кода. И, чем более древний и убогий код, тем чаще там встречается вот такое вот: A * p = new A; Более чем верный маркер того, что дальше будет треш, угар и содомия.
Ну ладно в древнем коде. Но, блин, в XXI-ом веке что заставляет писать вот это, когда давным-давно на всех углах говорят, что голые владеющие указатели -- это зло. Тем более, что эти указатели здесь, мягко говоря, вообще не нужны:
int main()
{
const auto show_params = [](const B & obj) {
for(const auto & p : obj.params()) { std::cout << p << ' '; }
std::cout << std::endl;
};
show_params(D1{});
show_params(D2{});
}
Но даже если у вас есть непреодолимое стремление создавать объекты именно в динамической памяти, то почему бы не воспользоваться умными указателями из стандартной библиотеки:
Так вот, вопрос к вам, как к человеку, который оперирует голыми владеющими указателями: что вами двигает? Вы намерено хотите создать проблемы тем, кто будет сопровождать код после вас?
То, что это игрушечный демонстрационный пример ответом не считается. Человек либо говнокодит везде, либо он изначально приучен обходить C++ные грабли.
Могу ошибаться, но вроде как в C++ до сих пор порядок инициализации статических объектов, размещенных в разных единицах трансляции, не определен. Так что если вот здесь:
окажется, что B::params_ и D1::params_ живут в разных единицах трансляции, то в какой-то прекрасный момент вы столкнетесь с тем, что при инициализации D1::params_ присходит обращение к еще не проинициализированному объекту B::params_.
Здравствуйте, so5team, Вы писали:
S>Не-не-не. Автору принципиально важно было иметь указатели на базовый тип. Поэтому я в своем примере auto не использовал.
Здравствуйте, Serg27, Вы писали:
S>Есть иерархия классов. Каждый класс имеет список имен ему нужных параметров, которые потом как-то используются как внутри класса так и извне его. Этот список постоянный для каждого класса. Причем в списке класса потомка присутствует весь список от базового класса. Написал решение. Упрощенный вариант см. ниже. Но можно ли как-то попроще/поизящней?
Путей для упрощения и повышения читаемости очень-очень много. Один из несложных:
Здравствуйте, so5team, Вы писали: S>Простите, что не по теме вашего вопроса. Но. S>По работе временами приходится заглядывать в дебри чужого кода. И, чем более древний и убогий код, тем чаще там встречается вот такое вот: A * p = new A; Более чем верный маркер того, что дальше будет треш, угар и содомия.
Я даже читать не стал дальше... Там же написано — упрощенный вариант. Про владеющие указатели я знаю лет 20, писал их сам, потом подоспели BOOST и STL. И использую. По теме идеи есть?
Здравствуйте, Serg27, Вы писали:
S>Я даже читать не стал дальше... Там же написано — упрощенный вариант. Про владеющие указатели я знаю лет 20, писал их сам, потом подоспели BOOST и STL. И использую. По теме идеи есть?
Спасибо. Можно сэкономить строчку. Хотя это поместит детали реализации в заголовочный файл. В моем случае не очень страшно.
Меня больше всего смущает, что придется повторять некоторые куски кода в каждом классе наследнике, а это copy-paste с возможными ошибками. Т.е. надо либо совсем сменить идею (метапрограммирование?), либо сделать что-то более вычурное на шаблонах. И то и другое получается у меня через чур сложно, а код будет жить долго и будет нужно его сопровождать.
Здравствуйте, Serg27, Вы писали:
S>Меня больше всего смущает, что придется повторять некоторые куски кода в каждом классе наследнике, а это copy-paste с возможными ошибками. Т.е. надо либо совсем сменить идею (метапрограммирование?), либо сделать что-то более вычурное на шаблонах. И то и другое получается у меня через чур сложно, а код будет жить долго и будет нужно его сопровождать.
Ну можно вообще не трогать объявления классов, а сделать отдельный глобальный объект, который будет позволять регистрировать параметры классов, хранить их в std::[unordered_]map<std::type_info*, params> и выдавать по запросу по typeid
Здравствуйте, ArtDenis, Вы писали:
AD>Ну можно вообще не трогать объявления классов, а сделать отдельный глобальный объект, который будет позволять регистрировать параметры классов, хранить их в std::[unordered_]map<std::type_info*, params> и выдавать по запросу по typeid
Нечто подобное сделано на другом уровне, там регистрируются объекты этих классов. И именно там на этом уровне нужен список параметров, которые используются данным объектом, чтобы при изменении величин параметров "дернуть" именно нужные объекты (ну и еще для некоторых вещей...). Список параметров известен при написании конкретного производного класса и в общем никому больше не интересен (ну кроме собственно "хранилища" этих параметров).