psilogic: (Default)
psilogic ([personal profile] psilogic) wrote2009-07-14 04:31 pm

Западло

[ Предупреждение: для непрограммистов неинтересно ]

Пусть у нас есть два класса - базовый Base и отнаследованный от него Derived. В Derived есть конструктор, похожий на конструктор копии с параметром типа Base.

class Base
{
...
};

class Derived: public Base
{
public:
    Derived() {...}
    Derived(const Base &b) { /* важные манипуляции */ }
};


Допустим, в программе это используется вот так:

Derived d1;
Derived d2(d1);


И оно не работает.

Тщательное расследование показало эпическое западло...



В какой-то момент я внес часть кода в функцию:

void foo(Base &d1)
{
    Derived d2(d1);
    ...
}
...
Derived d1;
foo(d1);



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

Западло состоит в том, что в строке Derived d2(d1) не всегда вызывается второй конструктор и не будут выполняться "важные манипуляции". Вместо этого будет вызван "невидимый" автоматически сгенерированный конструктор-копии, и все поля будут тупо скопированы из d1 в d2.

Это происходит в том случае, если d1 имеет тип Derived. Если Base - то все хорошо. Вот почему та функция исправляла проблему. Так тоже будет работать:

Derived d2((Base&)d1);


Лечится это легко:

class Base
{
...
};

class Derived: public Base
{
public:
    Derived() {...}
    Derived(const Base &b) { /* важные манипуляции */ }
    Derived(const Derived &b) { /* важные манипуляции */ }
};


Но ведь и вляпаться тоже легко...

[identity profile] alisarin.livejournal.com 2009-07-15 06:18 am (UTC)(link)
Не понимаю о чем это, но смеюсь над тем _как_это_ :))

[identity profile] psilogic.livejournal.com 2009-07-15 07:47 am (UTC)(link)
Интересно, что именно показалось зобавным? :)

[identity profile] alisarin.livejournal.com 2009-07-15 08:52 am (UTC)(link)
Конструкции (или типы данных - не знаю, может и то, и другое) в разных случаях сопровождаются разными ограничениями, то бишь универсальность не обеспечена :)

[identity profile] psilogic.livejournal.com 2009-07-15 09:13 am (UTC)(link)
Иногда ограничения - это очень полезно. Скажем, некая величина обозначается словом size и обозначает размер. Но в программе может быть тыща разных размеров. Удобно все их называть size, но чтобы при этом изменение одного size не влияло на изменение другого. Так что каждый size имеет как бы "область применимости", которая ограничена.

[identity profile] alisarin.livejournal.com 2009-07-15 09:31 am (UTC)(link)
Я, грешным делом, думал, что такое появляется под влиянием английской фонетики: начальный звук "civil" и "concrete" очень непохож, а буква "c" - одна и та же :)

Когда же тип состоит из подтипов, и последние используются, но как подтипы не определяются, ... хозяин - барин :))

[identity profile] psilogic.livejournal.com 2009-07-15 09:37 am (UTC)(link)
Такое появляется под влиянием многозначности естественного языка. Слово "стол" может означать самые разные столы в зависимости от контекста.

[identity profile] alisarin.livejournal.com 2009-07-15 09:43 am (UTC)(link)
Но лингвистика, можно сказать, на полпути к систематизации этих неопределенностей, понятие "омонима" тебе известно, остальные частности, хотя и в вольном изложении, представлены здесь, ... хотя и в вольном изложении.

[identity profile] psilogic.livejournal.com 2009-07-15 09:45 am (UTC)(link)
Лингвистика, может, и на полпути, а компьютерщики давно систематизировали и вовсю используют :)

[identity profile] alisarin.livejournal.com 2009-07-15 09:52 am (UTC)(link)
Логика, ну ... безгранична. "Неопределенности систематизированы в том смысле, что они используются как 'несистематизированные неопределенности'" ... ;-)