LINUX.ORG.RU

Правильная инициализация поля в C++

 


0

1

Привет. Есть одна^Wодин класс, а в классе поле. Это поле 100% будет будет инициальзироваться в одно действие, и наккой логики при его инициализации / удалении нет. Имеет ли смысл сделать его публичным, или стоит сделать приватным и написать функции для работы с ним?
Поясните как лучше.


Не выноси данные в паблик, оборачивай доступ через геттер/сеттер. Не совсем понял, при чем тут инициализация.

panter_dsd ★★★★
()

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

поясни, что ты хотел услышать?

anonymous
()

Привет. Есть одна^Wодин класс, а в классе поле. Это поле 100% будет будет инициальзироваться в одно действие, и наккой логики при его инициализации / удалении нет

сделай приватный enum. Или приватный static const(хуже). Или просто приватный const(ещё хуже). Как получится.

drBatty ★★
()
Ответ на: комментарий от actics

я хотел услышать как лучше присваивать значение

class foo{
foo() : bar(42) {}
};

и не путай инициализацию с присваиванием. operator= и конструктор копирования - это совершенно другая ерунда, только с виду похоже.

drBatty ★★
()
Ответ на: комментарий от actics

Ну не иницализация, просто присвоение значений. Почему лучше делать через геттер сеттер?

вообще-то в C++ имеется встроенный сеттер, даже два. Конструктор копирования и оператор=. По дефолту они побайтно копируют все поля. Но можешь перезагрузить. ИМХО если не знаешь, лучше перезагрузи и сделай приватными. Что-бы кто-то случайно не написал bar=42, что вообще может привести к фейлу, ежели 42 преобразуется в bar, а потом туда побитно запишется.

drBatty ★★
()
Ответ на: комментарий от actics

Функции типа set/get удобны тем, что туда ты можешь засунуть какую-то дополнительную логику, не переписывая тонны кода. Если ты абсолютно уверен, что оно тебе не понадобится, то без разницы

Gvidon ★★★★
()
Ответ на: комментарий от drBatty

Мне все таки нужно присваивать. Правда я только что понял, что эти поля у мня не смотрят наржу и я их сделаю приватными. Однако вопрос остается в силе.

И заодно ещё спрошу: как православней инициализировать поля в конструкторе?

class foo() {
    foo() : bar(42) {}
}
или
class foo() {
    foo() {bar = 42;}
}
В чем разница?

actics
() автор топика
Ответ на: комментарий от actics

В первом случае у тебя отработает конструктор, а во втором - оператор копирования.

Gvidon ★★★★
()
Ответ на: комментарий от actics
#include <iostream>

struct A
{
  A() {}
  A(const A &a) { std::cout << "ctor" << std::endl; }
  A& operator=(const A &a) { std::cout << "operator" << std::endl; }
};

struct B
{
  A aa;
  B(const A &a): aa(a) {}
};

struct C
{
  A aa;
  C(const A &a) { aa = a; }
};

int main()
{
  A a;
  B b(a);
  C c(a);
}
bash-4.1$ ./a.out 
ctor
operator
Gvidon ★★★★
()

Если поле имеет встроенный или POD-тип, и при присвоении-чтении никаких дополнительных действий (типа флажков, логирования) не производится, геттеры-сеттеры не нужны. Серьёзно. Keep it simple.

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

schizoid ★★★
()

Интерфейс должен быть единообразным. И присваивать часть полей напрямую, а часть - через сеттер, по меньшей мере, странно.

keyran ★★
()
Ответ на: комментарий от panter_dsd

Это не Java, тонны геттеров/сеттеров для POD которые ничего не делают, означает только одно: надо убрать их убрать и переименовать class в struct.

bjorn
()
Ответ на: комментарий от Gvidon

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

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 2)
Ответ на: комментарий от actics

Мне все таки нужно присваивать. Правда я только что понял, что эти поля у мня не смотрят наржу и я их сделаю приватными. Однако вопрос остается в силе.

используй operator=() для копирования. Это такой сеттер. И/или конструктор копирования(для инициализации). Если это не нужно, просто сделай их пустыми и приватными.

И заодно ещё спрошу: как православней инициализировать поля в конструкторе?

конечно foo() : bar(42)

Это специальная форма, и иногда правильно работает только она. Другой способ не правильный. К тому-же, первый вариант НЕ нуждается в коде, т.е. может быть намного быстрее. (хотя умный компилятор может догадаться, что второй вариант тоже не требует кода. У тебя умный компилятор и ты тоже умный? Тогда пиши как хочешь).

drBatty ★★
()
Ответ на: комментарий от keyran

Интерфейс должен быть единообразным. И присваивать часть полей напрямую, а часть - через сеттер, по меньшей мере, странно.

это C++. Тут _только_ через сеттер. Напрямую не получится(т.е. можно foo.bar =42, но это быдлокод, если конечно foo не POD.

drBatty ★★
()
Ответ на: комментарий от bjorn

Это не Java, тонны геттеров/сеттеров для POD которые ничего не делают, означает только одно: надо убрать их убрать и переименовать class в struct.

+1, однако class в struct можно и не переименовывать. (хотя стилистически лучше переименовать)

drBatty ★★
()

есть книжка хорошая, scott meyers effective c++. Там написано про все что ты спрашиваешь и даже больше!

nokachi
()
Ответ на: комментарий от drBatty

Другой способ не правильный.

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

nokachi
()
Ответ на: комментарий от nokachi

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

думаешь, ТС этого ждал?

drBatty ★★
()

Срочно прочти Майерса. У него как раз про то что ты спрашиваешь.

KblCb ★★★★★
()

Если у тебя есть ф-ия, ты всё ещё имеешь контроль над представлением этой сущности в классе на уровне языка. Если надо будет поменять представление - поменял одну ф-ию и перекомпелировал.

Если у тебя есть паблик варибл - как только возникнет проблема представления будешь ворошить всю прогу в поисках ссылок на неё.

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

nanoolinux ★★★★
()

при «ЖЕЛАНИИ» функция злоумышленик сможет писать твоё приват поле через приведение к структуре и записи по нужному смещению.

поэтому причина почему скрывают поля - не загромождать пространстово имён(даже квалифицированных) и не провоцировать усиление связаности.

поля не удаляются отдельно от обьекта. ибо обьект и есть набор полей.

не делай досрочной сверхобобщённости . пусть публичное поле.

ну и вообще может тебе структуры достаточно?

qulinxao ★★☆
()

покури Страустропа(ага это тот кто С++ )

ну нафиг всё через обьекты делать.

посмотри на абстракции как на общие протоколы/интерфейсы.

забавно что наследование прямо нарушает инкапсюляцию.

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

Структуры недостаточно, мне там нужен интерфейс.
Вот сверху ещё посоветовали писать getter / setter в хедере. Можно же явно сказать inline и тогда будут счастливы все - и фанаты java и те кто за скорость. Это хорошая идея?
И да, сработает ли инлайн при присвоении к приватному полю?

actics
() автор топика
Ответ на: комментарий от nanoolinux

Инлайны!) спасибо, надо обдумать

actics
() автор топика
Ответ на: use c++11 от ckotinko

!! Спасибо, это действительно хорошая идея) Как я понимаю, это будет аналогично X() : n(5), bar(1,«foofoofoo») {} ?

actics
() автор топика
Ответ на: комментарий от actics

полу грамотность сочетает в себе худшие черты не грамотности и грамотности

тебе вообще зачем обьект в сравнение с pod?

qulinxao ★★☆
()

Вытаскивая переменную-член в паблик ты нарушаешь инкапсуляцию, перестаешь контролировать инвариант и убиваешь котенка.

m0rph ★★★★★
()
Ответ на: комментарий от actics

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

x0r ★★★★★
()
Ответ на: комментарий от drBatty

в C++ имеется встроенный сеттер, даже два

тут надо взять в кавычки слово сеттер. я конструктор с деструктором даже методами называть не люблю, они явно не вызываются, кроме как при использовании в качестве delegate constructors.

x0r ★★★★★
()
Ответ на: комментарий от m0rph

о какой инкапсуляции идет речь, если у аттрибута есть публичный селектор и модификатор без дополнительной логики?

x0r ★★★★★
()
Ответ на: комментарий от x0r

Я путаюсь в поняшах ><
Тут все логично учили. Для этого и были придуманы приватные штуки же ) Вот только зачем статик конст высовывать наружу, если его не юзают?

actics
() автор топика
Ответ на: комментарий от actics

Вот сверху ещё посоветовали писать getter / setter в хедере. Можно же явно сказать inline и тогда будут счастливы все - и фанаты java и те кто за скорость. Это хорошая идея?

плохая. Потому-что это НЕ Java. Будет ява - спроси у кого-нить ещё.

И да, сработает ли инлайн при присвоении к приватному полю?

конечно да. Он может НЕ сработать с пабликом, если этот паблик где-то далеко (в хидере например). А с приватным полем ты его от кода не оторвёшь.

drBatty ★★
()
Ответ на: комментарий от actics

да у меня вообще pod поля

тогда совет выше - будь проще, не заморачивайся. Делать тут конструкторы/сеттеры == получить по роже. Ибо от тебя твои товарищи такого не ждут. Кому-то придётся ночку в дебагере посидеть. из-за тебя.

Хотя синтаксис и позволяет конечно…

drBatty ★★
()
Ответ на: комментарий от actics

твой ответ саморекомендация себе курнуть lang def C++

qulinxao ★★☆
()
Ответ на: комментарий от actics

Спасибо, это действительно хорошая идея) Как я понимаю, это будет аналогично X() : n(5), bar(1,«foofoofoo») {} ?

типа того. Напоминает

if (cmd[1] == RESET)    // если принятая команда RESET
{((void(*)(void))0)();} // что-то из черной магии

drBatty ★★
()
Ответ на: комментарий от drBatty

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

actics
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.