Re[20]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 08:01
Оценка: 2 (2)
Здравствуйте, Bork, Вы писали:

B>Здравствуйте, sergey_shandar, Вы писали:


_>>Не вижу у класса C явного (user-defined) конструктора копирования.


B>а причем здесь класс С ? с ним то как раз проблем нету

B>или ты считаешь, что если у С нет явно определенного конструктора копирования, то компилятор и в В должен его сам определять ?

Есть люди которые бояться признавать свои ошибки. Пока.
getboost.codeplex.com
citylizard.codeplex.com
Re[11]: Копирование базовых под
От: Bork СССР  
Дата: 13.08.04 05:08
Оценка: :)
Здравствуйте, sergey_shandar, Вы писали:

спасибо за перевод, а то я бы сам не догадался

попробую еще разик ....

вот это — стандартное поведение компилятора, которое и описывает твоя выдержка из стандарта
<псевдокод>
C(const C&)
{
B(operator B(C)) — конструирование базового класса с применением неявного приведения типа
С(С) — конструирование инстанцируемого класса
}
operator B(const C&) — оператор приведения типа

так и происходит в твоем примере при отсутствии конструктора B(C). но введя его ты сам, добровольно, меняешь логику принятую по умолчанию, т.к. в дело вступает другая строка стандарта (искать не буду) о применении неявного приведения типа. и эта строка стандарта явно запрещает это приведение в слуае если определена функция с точной сигнатурой. что и происходит в твоем случае.
Re[15]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:07
Оценка: :)
Здравствуйте, dupamid, Вы писали:

D>Здравствуйте, Bork, Вы писали:


D>Псевдокода, который ты написал нет в Стандарте, там просто сказано что должен генерироваться конструктор копирования, который выполняет копирование всех подобъектов. Более того, этот мой пример противоречит твоей трактовке поведение MSVC:


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


D>
D>#include <stdio.h>

D>struct A;
D>struct B;

D>struct A
D>{
D>    A(){}
D>    A(const B&)
D>    {
D>        printf("A::A(const B&)\n");
D>    }
D>};

D>struct B
D>{
D>    B(){}
D>    B(const A&)
D>    {
D>        printf("B::B(const A&)\n");
D>    }
D>};

D>struct C : A, B
D>{
D>};

D>int main()
D>{
D>    C c1;
D>    C c2(c1);
D>}
D>

D>Следуя твоей логике он должен выдеть здесь неоднозначность, а он успешно выбирает конструктор копирования.

а здесь нет никакого противоречия, т.к. согласно объявлению класса С конструирование происходит следующим образом :

1. вызов конструктора класса А, с передачей ему объекта с1.
класс A не знает как преобразовать класс С в класс В, но знает как превратиь С в А поэтому генерируется конструктор по умолчанию A(operator А(С)), который и вызывается.

2. вызов конструктора класса B, с передачей ему объекта с1.
здесь происходит тоже самое что и в п.1

3. вызов конструктора С(С).

результат — вывода на экран не происходит.
так что пример не удачен.

хм..
но самое интересное, что конструкторы
A(const C&)
{
printf("A::A(const C&)\n");
}
и
B(const C&)
{
printf("B::B(const C&)\n");
}
тоже вызываться не будут если параллельно не будут объявлены стандартные конструкторы копирования
A(const A&) и B(const B&) ... а вот это уже косяк
Копирование базовых подобъектов
От: Bork СССР  
Дата: 13.08.04 02:23
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

Определение типа B:

struct C;
struct B
{
    B() {}
    B(const B &) { std::cout << "copy constructor" << std::endl; }
    B(const C &) { std::cout << "[cencored] constructor" << std::endl; }
};

--
ПК

_>Тип C, третий случай:

_>
_>struct C: B {};
_>

_>Вывод GCC 3.3.1, IMHO, правильно:
_>
_>copy constructor
_>

_>Вывод VC 7.1, IMHO, неправильно, бред какой то:

1. а не бред объявит в базовом классе конструктор, принимающий на вход экземпляр производного класса ?
2. компилятор естественно вызывает конструктор B(C), т.к. ему в этом случае не нужно преобразования типа (т.е. его поведение вполне соответствует стандарту), а если хочется другого (не стандартного)поведения, то сделай сам явное преобразование (твой пример выше это и демонстрирует). а вот поведение GCC мягко говоря некоректно.


26.08.04 02:07: Ветка выделена из темы Рекурсивный вызов конструктора на VC 7.1.
Автор: sergey_shandar
Дата: 11.08.04
— Павел Кузнецов
Re[4]: Копирование базовых подо
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 02:53
Оценка:
Здравствуйте, Bork, Вы писали:

B>1. а не бред объявит в базовом классе конструктор, принимающий на вход экземпляр производного класса ?

Гм... Мининимальный пример показывающий ошибку в компиляторе не являеться бредом, если он показывает ошибку в компиляторе. Искать какую то другую смысловую нагрузку в таком примере можно, но это offtopic.

B>2. компилятор естественно вызывает конструктор B(C), т.к. ему в этом случае не нужно преобразования типа (т.е. его поведение вполне соответствует стандарту),

Не соответствует стандарту. См. стандарт:

12.8.8.
The implicitly-defined copy constructor for class X performs a memberwise copy of its subobjects. The
order of copying is the same as the order of initialization of bases and members in a user-defined constructor
(see 12.6.2). Each subobject is copied in the manner appropriate to its type:
if the subobject is of class type, the copy constructor for the class is used;
— if the subobject is an array, each element is copied, in the manner appropriate to the element type;
— if the subobject is of scalar type, the built-in assignment operator is used.

getboost.codeplex.com
citylizard.codeplex.com
Re[5]: Копирование базовых подо
От: Bork СССР  
Дата: 13.08.04 03:24
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Не соответствует стандарту. См. стандарт:

_>

_>12.8.8.
_>The implicitly-defined copy constructor for class X performs a memberwise copy of its subobjects. The
_>order of copying is the same as the order of initialization of bases and members in a user-defined constructor
_>(see 12.6.2). Each subobject is copied in the manner appropriate to its type:
_>— if the subobject is of class type, the copy constructor for the class is used;
_>— if the subobject is an array, each element is copied, in the manner appropriate to the element type;
_>— if the subobject is of scalar type, the built-in assignment operator is used.



хехе ключевое слово в этой выдержке — "The implicitly-defined copy constructor". А где в своем примере ты видишь это implicitly-defined ? если у тебя определен пользовательский конструктор B(C), который подходит к ситуации лучше, т.к. не требует приведения типов.
Re[6]: Копирование базовых подо
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 03:41
Оценка:
Здравствуйте, Bork, Вы писали:

B>хехе ключевое слово в этой выдержке — "The implicitly-defined copy constructor". А где в своем примере ты видишь это implicitly-defined ? если у тебя определен пользовательский конструктор B(C), который подходит к ситуации лучше, т.к. не требует приведения типов.


См. пример внимательно:
struct C;
struct B
{
    B() {}
    B(const B &) { std::cout << "copy constructor" << std::endl; }
    B(const C &) { std::cout << "[cencored] constructor" << std::endl; }
};
struct C: B {}; ///< строка 8.


В строке 8 компилятор должен создавать правильный "The implicitly-defined copy constructor", который должен вызывать для каждого "of its subobjects" "the copy constructor", т.е. B::B(const B &). А вызываеться B(const C &), т.е. бред какой то, ч.т.д.
getboost.codeplex.com
citylizard.codeplex.com
Re[7]: Копирование базовых подо
От: Bork СССР  
Дата: 13.08.04 04:11
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>См. пример внимательно:

_>
_>struct C;
_>struct B
_>{
_>    B() {}
_>    B(const B &) { std::cout << "copy constructor" << std::endl; }
_>    B(const C &) { std::cout << "[cencored] constructor" << std::endl; }
_>};
_>struct C: B {}; ///< строка 8.
_>


_>В строке 8 компилятор должен создавать правильный "The implicitly-defined copy constructor", который должен вызывать для каждого "of its subobjects" "the copy constructor", т.е. B::B(const B &). А вызываеться B(const C &), т.е. бред какой то, ч.т.д.


это с какой такой великой радости он это должен ?
в строке 8 компилятор должен создаеть такое:

<псевдокод>
C(const C&)
{
B(C) — конструирование базового класса
С(С) — конструирование инстанцируемого класса
}

что он и делает. если бы не был определен конструктор B(const C&), то компилятор бы сделал дополнительную функцию для приведения типа и вызов бы был таким:

<псевдокод>
C(const C&)
{
operator B(const C&) — оператор приведения типа
B(operator B(C)) — конструирование базового класса
С(С) — конструирование инстанцируемого класса
}

но в данном случае этого не происходит, т.к. преобразованием типа компилятор занимается только если отсутствуют явно определенные функции с подходящей сигнатурой, а в твоем примере они присутствуют (конструктор B(C)). ты же требуешь от компилятора фактически того, что раз для производного класса конструктор копирования не определен, то считать не определенными и конструкторы в производных классах (т.е. автоматически генерировать и их, т.к. в этом случае B(B) ничем не лучше B(C), т.е. на твою версию B(B) надо забить, а это нонсенс)
Re[8]: Копирование базовых подо
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 04:27
Оценка:
Здравствуйте, Bork, Вы писали:

B>Здравствуйте, sergey_shandar, Вы писали:


_>>См. пример внимательно:

_>>
_>>struct C;
_>>struct B
_>>{
_>>    B() {}
_>>    B(const B &) { std::cout << "copy constructor" << std::endl; }
_>>    B(const C &) { std::cout << "[cencored] constructor" << std::endl; }
_>>};
_>>struct C: B {}; ///< строка 8.
_>>


_>>В строке 8 компилятор должен создавать правильный "The implicitly-defined copy constructor", который должен вызывать для каждого "of its subobjects" "the copy constructor", т.е. B::B(const B &). А вызываеться B(const C &), т.е. бред какой то, ч.т.д.


B>это с какой такой великой радости он это должен ?


По логике и по стандарту, см. ВНИМАТЕЛЬНО 12.8.8
Автор: sergey_shandar
Дата: 13.08.04
, а то мы ходим по кругу. Преобразования типов здесь вообще ни при чем.
getboost.codeplex.com
citylizard.codeplex.com
Re[9]: Копирование базовых подо
От: Bork СССР  
Дата: 13.08.04 04:32
Оценка:
Здравствуйте, sergey_shandar, Вы писали:


_>По логике и по стандарту, см. ВНИМАТЕЛЬНО 12.8.8
Автор: sergey_shandar
Дата: 13.08.04
, а то мы ходим по кругу. Преобразования типов здесь вообще ни при чем.


как это ни при чем ? а где компилятор должен взять это B? чтобы вызвать B(B) ?

c одной стороны ты требуешь побитового (memberwise) копирования (ссылаясь на стандарт), а с другой создаешь пользовательские конструкторы на разные случаи жизни. из этого следует 2 вывода:

1. ни о каком побитовом копировании речи уже не идет, т.к. мало ли что ты делаешь в конструкторе копирования (компилятор эб этом не знает).
2. определение B(C) прямо предписывает компилятору использовать конструктор B(C), если это самое С ему на вход подается. в данном контексте, если производный класс С, то использовать B(C), если любой другой, то использовать B(B). что компилятор послушно и делает
Re[10]: Копирование базовых под
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 04:52
Оценка:
Здравствуйте, Bork, Вы писали:

_>>По логике и по стандарту, см. ВНИМАТЕЛЬНО 12.8.8
Автор: sergey_shandar
Дата: 13.08.04
, а то мы ходим по кругу. Преобразования типов здесь вообще ни при чем.


B>как это ни при чем ? а где компилятор должен взять это B? чтобы вызвать B(B) ?


B>c одной стороны ты требуешь побитового (memberwise) копирования (ссылаясь на стандарт), а с другой создаешь пользовательские конструкторы на разные случаи жизни. из этого следует 2 вывода:


Это такой способ издеваться? Перевожу:

12.8.8.
Неявный конструктор копирования для класса X (в нашем случае C) выполняет копирование его составляющих (причем здесь побитовое копирование bitwise copy?). Порядок копирования такой же как и порядок инициализации баз (или наследуемых классов, как Вам больше нравиться) и членов (мемберов, полей и т.п.) в определенном пользователем конструкторе (см. 12.6.2). Каждый такая составляющая копируеться в соответствии с её типом:
— если это class (как в нашем случае B), то используеться конструктор копирования этого класса (т.е. B::B(const B &), а не B::B(const C&)).
— если это массив, то каждый элемент этого массива копируеться в соотвествии с его типом.
— если это скалярный тип, то вызываеться встроенный оператор присваивания.

Все....
getboost.codeplex.com
citylizard.codeplex.com
Re[10]: Копирование базовых под
От: folk Россия  
Дата: 13.08.04 05:00
Оценка:
Здравствуйте, Bork, Вы писали:

_>>По логике и по стандарту, см. ВНИМАТЕЛЬНО 12.8.8
Автор: sergey_shandar
Дата: 13.08.04
, а то мы ходим по кругу. Преобразования типов здесь вообще ни при чем.


B>как это ни при чем ? а где компилятор должен взять это B? чтобы вызвать B(B) ?


B>c одной стороны ты требуешь побитового (memberwise) копирования (ссылаясь на стандарт), а с другой создаешь пользовательские конструкторы на разные случаи жизни. из этого следует 2 вывода:


B>1. ни о каком побитовом копировании речи уже не идет, т.к. мало ли что ты делаешь в конструкторе копирования (компилятор эб этом не знает).

B>2. определение B(C) прямо предписывает компилятору использовать конструктор B(C), если это самое С ему на вход подается. в данном контексте, если производный класс С, то использовать B(C), если любой другой, то использовать B(B). что компилятор послушно и делает

Вот ведь упорный какой Не надо ничего додумывать.

В цитате английским языком было сказано, что для инициализации подобъектов используется конструктор копирования. А конструктором копирования класса X является конструктор, первый параметр которого имеет тип X&, X const&, X volatile& или X const volatile& (12.8/2). Так что конструктор B(C) не является конструктором копирования и таким образом не может быть выбран.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[11]: Копирование базовых под
От: Bork СССР  
Дата: 13.08.04 05:16
Оценка:
Здравствуйте, folk, Вы писали:

F>Вот ведь упорный какой Не надо ничего додумывать.


а ничего не додумывается
просто в данном конкретном примере вступают в противоречие 2 предписания:
1. вызов конструктора копирования
2. запрет неявного приведения типа при наличии определениия функции с точной сигнатурой.

какое из этих предписаний важнее ?
MS посчитала, что второе ...
Re[12]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 05:41
Оценка:
Здравствуйте, Bork, Вы писали:

B>а ничего не додумывается

B>просто в данном конкретном примере вступают в противоречие 2 предписания:
B>1. вызов конструктора копирования
Спасибо за то что приняли правила неявного копирования.

B>2. запрет неявного приведения типа при наличии определениия функции с точной сигнатурой.

Теперь по поводу противоречий, можно пункт из стандарта, который противоречит 12.8.8?
getboost.codeplex.com
citylizard.codeplex.com
Re[13]: class member access question
От: Bork СССР  
Дата: 13.08.04 06:12
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Bork, Вы писали:


B>>а ничего не додумывается

B>>просто в данном конкретном примере вступают в противоречие 2 предписания:
B>>1. вызов конструктора копирования
_>Спасибо за то что приняли правила неявного копирования.
так я и не отказывался

B>>2. запрет неявного приведения типа при наличии определениия функции с точной сигнатурой.

_>Теперь по поводу противоречий, можно пункт из стандарта, который противоречит 12.8.8?

правила неявного преобразования типов параметров при вызове функций что ли ? так поищи их сам, тем более что стандарт у тебя под рукой. ну и естественно что там не написано о том, что такой то пункт противоречит пункту 12.8.8.
но вспомни механизм работы конструктора, порядок вызова конструкторов базовых классов, порядок инициализации членов и подумай откуда берутся параметры для неявного конструктора копирования.
и ты тоже увидишь проблему в своем примере, которую MS трактует в пользу приведения типа, а разработчики GCC в пользу конструктора копирования. кто из них прав с точки зрения стандарта я сказать не могу, имею лишь свое мнение, которое склоняется в сторону MS, т.к. логически более выдержанное (опять же с моей точки зрения).
Re[13]: class member access question
От: Bork СССР  
Дата: 13.08.04 06:23
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Bork, Вы писали:


давай рассмотрим такой пример

struct C;
struct B
{
void fn(const B &) { std::cout << "class B" << std::endl; }
void fn(const C &) { std::cout << "class C" << std::endl; }
};

struct C: B {};
struct D: B {};

int _tmain(int argc, _TCHAR* argv[])
{
C c;
c.fn(c); // выводит "class C"
D d;
d.fn(d); // выводит "class B"
return 0;
}

надеюсь результат тебя не обескураживает ?
так чем же конструкторы то лучше ? с точки зрения языка такие же функции, к которым применимы те же правила приведения типов
Re[14]: class member access question
От: dupamid Россия  
Дата: 13.08.04 06:39
Оценка:
Здравствуйте, Bork, Вы писали:

B>давай рассмотрим такой пример


B>struct C;

B>struct B
B>{
B> void fn(const B &) { std::cout << "class B" << std::endl; }
B> void fn(const C &) { std::cout << "class C" << std::endl; }
B>};

B>struct C: B {};

B>struct D: B {};

B>int _tmain(int argc, _TCHAR* argv[])

B>{
B> C c;
B> c.fn(c); // выводит "class C"
B> D d;
B> d.fn(d); // выводит "class B"
B> return 0;
B>}

B>надеюсь результат тебя не обескураживает ?

B>так чем же конструкторы то лучше ? с точки зрения языка такие же функции, к которым применимы те же правила приведения типов

Псевдокода, который ты написал нет в Стандарте, там просто сказано что должен генерироваться конструктор копирования, который выполняет копирование всех подобъектов. Более того, этот мой пример противоречит твоей трактовке поведение MSVC:
#include <stdio.h>

struct A;
struct B;

struct A
{
    A(){}
    A(const B&)
    {
        printf("A::A(const B&)\n");
    }
};

struct B
{
    B(){}
    B(const A&)
    {
        printf("B::B(const A&)\n");
    }
};

struct C : A, B
{
};

int main()
{
    C c1;
    C c2(c1);
}

Следуя твоей логике он должен выдеть здесь неоднозначность, а он успешно выбирает конструктор копирования.
Re[14]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 06:45
Оценка:
Здравствуйте, Bork, Вы писали:

B>давай рассмотрим такой пример


скипнуто

B>надеюсь результат тебя не обескураживает ?

Нет, не обескураживает.

B>так чем же конструкторы то лучше ?

Ничем.

B>с точки зрения языка такие же функции, к которым применимы те же правила приведения типов

И? А причем здесь то как генерируеться неявный конструктор?

По моей логике и по стандарту: неявный конструктор, должен вызывать конструктор копирования для каждой части класса. Так как части у двух одинаковых классов одинаковые (по своей структуре), то приведенея типов здесь совершенно не при чем. А если следовать тому что ты хочешь сказать, тогда и к таким примерам не долго дойти:
struct A {};
struct B: A
{
    A a;
    B(const B &b_): A(b_), a(b_) {}
};

Никакого явного приведения типов, наслаждайся ....
getboost.codeplex.com
citylizard.codeplex.com
Re[15]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:12
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Bork, Вы писали:


B>>с точки зрения языка такие же функции, к которым применимы те же правила приведения типов

_>И? А причем здесь то как генерируеться неявный конструктор?

так в твоем то примере он как раз и не генерируется, а определяется тобой
а вот если его не определить, то он как раз и будет сгенерирован и вызова B(C) не произойдет

_>По моей логике и по стандарту: неявный конструктор, должен вызывать конструктор копирования для каждой части класса. Так как части у двух одинаковых классов одинаковые (по своей структуре), то приведенея типов здесь совершенно не при чем. А если следовать тому что ты хочешь сказать, тогда и к таким примерам не долго дойти:

_>
_>struct A {};
_>struct B: A
_>{
_>    A a;
_>    B(const B &b_): A(b_), a(b_) {}
_>};
_>

_>Никакого явного приведения типов, наслаждайся ....

ну a(b_) это конечно крута
Re[16]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:14
Оценка:
Здравствуйте, Bork, Вы писали:

B>тоже вызываться не будут если параллельно не будут объявлены стандартные конструкторы копирования

B>A(const A&) и B(const B&) ... а вот это уже косяк

впрочем при размышлении так и должно быть, потому что при отсутствии конструктора копирования выбирать не из чего и он (конструктор копирования) генерируется компилятором
Re[16]: class member access question
От: dupamid Россия  
Дата: 13.08.04 07:16
Оценка:
Здравствуйте, Bork, Вы писали:

D>>Псевдокода, который ты написал нет в Стандарте, там просто сказано что должен генерироваться конструктор копирования, который выполняет копирование всех подобъектов. Более того, этот мой пример противоречит твоей трактовке поведение MSVC:


B>это был не псевдокод, а реальная программа, которая работает как ожидается


Ты же писал что это псевдокод http://www.rsdn.ru/Forum/Message.aspx?mid=761618&amp;only=1
Автор: Bork
Дата: 13.08.04
. Если ты считаешь это настоящим кодом, то видимо спорить вообще безсмысленно...

D>>Следуя твоей логике он должен выдеть здесь неоднозначность, а он успешно выбирает конструктор копирования.


B>а здесь нет никакого противоречия, т.к. согласно объявлению класса С конструирование происходит следующим образом :


B>1. вызов конструктора класса А, с передачей ему объекта с1.

B>класс A не знает как преобразовать класс С в класс В, но знает как превратиь С в А поэтому генерируется конструктор по умолчанию A(operator А(С)), который и вызывается.

Почему это класс А не знает как преобразовать С в B? Отлично знает это точно такое же преобразование производный -> базовый как C -> A.

B>2. вызов конструктора класса B, с передачей ему объекта с1.

B>здесь происходит тоже самое что и в п.1

B>3. вызов конструктора С(С).


Какого конструктора С? Это и так конструктор С, один конструктор вызывает другой конструктор того же класса???

B>хм..

B>но самое интересное, что конструкторы
B>A(const C&)
B>{
B> printf("A::A(const C&)\n");
B>}
B>и
B>B(const C&)
B>{
B> printf("B::B(const C&)\n");
B>}
B>тоже вызываться не будут если параллельно не будут объявлены стандартные конструкторы копирования
B>A(const A&) и B(const B&) ... а вот это уже косяк

Это как раз правильно! В сгенерированной компилятором конструкторе копирования, могут вызываться только конструкторы копирования.
Re[16]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 07:17
Оценка:
Здравствуйте, Bork, Вы писали:

_>И? А причем здесь то как генерируеться неявный конструктор?


B>так в твоем то примере он как раз и не генерируется, а определяется тобой


Где?
getboost.codeplex.com
citylizard.codeplex.com
Re[17]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:34
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, Bork, Вы писали:


_>>И? А причем здесь то как генерируеться неявный конструктор?


B>>так в твоем то примере он как раз и не генерируется, а определяется тобой


_>Где?


ну собственно вот с чего я начал:

твой код ...
_>struct C;
_>struct B
_>{
_> B() {}
_> B(const B &) { std::cout << "copy constructor" << std::endl; }
_> B(const C &) { std::cout << "[cencored] constructor" << std::endl; }
_>};

_>struct C: B {};



_>Вывод GCC 3.3.1, IMHO, правильно:

_>copy constructor


_>Вывод VC 7.1, IMHO, неправильно, бред какой то:

_>[cencored] constructor


_>Программа:

_>int main()
_>{
_> C c;
_> C c1 = c;
_> return 0;
_>}

т.е. вопрос — бред или не бред ?

поразмыслив и поэкспериментировав я получил след. вывод:
логика работы компилятора такая:

если (не определен конструктор копирования ?)
генерируем и выполняем его
иначе { // т.е. определен
выбираем чего вызвать на исполнение
и вот тут то компилятор обнаруживает 2 функции
B(const B &) и B(const C &)
а на входе то С, значит первая функция вызывается с приведением типа,
а вторая без него. следовательно вызывается B(const C &)
}

правильно это или нет, судить не буду, но вполне логично
Re[18]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 13.08.04 07:47
Оценка:
Здравствуйте, Bork, Вы писали:

_>>>И? А причем здесь то как генерируеться неявный конструктор?


B>>>так в твоем то примере он как раз и не генерируется, а определяется тобой


_>>Где?


B>ну собственно вот с чего я начал:


B>твой код ...


мой...

...
struct C: B {};
...


Не вижу у класса C явного (user-defined) конструктора копирования.

B>поразмыслив и поэкспериментировав я получил след. вывод:

B>логика работы компилятора такая:

B>если (не определен конструктор копирования ?)

B> генерируем и выполняем его
B>иначе { // т.е. определен
B> выбираем чего вызвать на исполнение
B> и вот тут то компилятор обнаруживает 2 функции
B> B(const B &) и B(const C &)
См. стандарт, компилятор ищет только конструктор копирования. Все остальное фантазии, это в отдельный топик.
getboost.codeplex.com
citylizard.codeplex.com
Re[17]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:50
Оценка:
Здравствуйте, dupamid, Вы писали:

D>Ты же писал что это псевдокод http://www.rsdn.ru/Forum/Message.aspx?mid=761618&amp;only=1
Автор: Bork
Дата: 13.08.04
. Если ты считаешь это настоящим кодом, то видимо спорить вообще безсмысленно...


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

B>>1. вызов конструктора класса А, с передачей ему объекта с1.

B>>класс A не знает как преобразовать класс С в класс В, но знает как превратиь С в А поэтому генерируется конструктор по умолчанию A(operator А(С)), который и вызывается.

D>Почему это класс А не знает как преобразовать С в B? Отлично знает это точно такое же преобразование производный -> базовый как C -> A.


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

B>>2. вызов конструктора класса B, с передачей ему объекта с1.

B>>здесь происходит тоже самое что и в п.1

B>>3. вызов конструктора С(С).


D>Какого конструктора С? Это и так конструктор С, один конструктор вызывает другой конструктор того же класса???


имеется ввиду исполнение непосредственного кода функции С(С).

D>Это как раз правильно! В сгенерированной компилятором конструкторе копирования, могут вызываться только конструкторы копирования.


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

class B;
class A
{
A(const A&) {}
A(const B&) {}
};

class B : A {};

void main()
{
B b1;
B b2(b1);
}

конструктор копирования A(const A&) не вызовется никогда, т.к. выбор в пользу A(const B&) предпочтительнее.
Re[19]: class member access question
От: Bork СССР  
Дата: 13.08.04 07:56
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Не вижу у класса C явного (user-defined) конструктора копирования.


а причем здесь класс С ? с ним то как раз проблем нету
или ты считаешь, что если у С нет явно определенного конструктора копирования, то компилятор и в В должен его сам определять ?

B>>поразмыслив и поэкспериментировав я получил след. вывод:

B>>логика работы компилятора такая:

_>См. стандарт, компилятор ищет только конструктор копирования. Все остальное фантазии, это в отдельный топик.


а компилятор и ищет и успешно его находит
вот только исполнять он его не будет, если найдет сигнатуру получше
т.к. считает тебя умнее себя, и раз ты выделил наряду с
B(const B&)
еще и
B(const С&)
то ты знаешь что делаешь
Re[21]: class member access question
От: Bork СССР  
Дата: 13.08.04 08:16
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Есть люди которые бояться признавать свои ошибки. Пока.


это ты о себе ?
уперевшись в п.12.8.8 не видишь ничего рядом ? но ведь стандарт состоит не только из этого пункта, а еще и существуют различные щекотливые моменты, типа твоего примера, где не все так однозначно и есть поле для размышлений MS решило его по своему, GCC другим способом. Вот только классифицировать это багом я бы не решился
Re[21]: class member access question
От: _Winnie Россия C++.freerun
Дата: 26.08.04 04:26
Оценка:
Здравствуйте, sergey_shandar, Вы писали:

_>Есть люди которые бояться признавать свои ошибки.


Ну вообще-то это ошибка microsoft. ^_^

Спасибо, добавил в свою коллекцию багов (да, я энтомолог)

//should print A, but MSVC7.1 print B
#include <iostream>

class B;
class A
{
public:
  A(){}
  A(const A&) { std::cout <<"A"; }
private:
  A(const B&) { std::cout <<"B"; }
};

class B :  A
{
};

void main()
{
  B b1;
  B b2(b1);
}


Попробовал скомпилировать IC++ c ключом /Qms1 и /Qms2(Instructs the compiler to enable most Microsoft compatibility bugs./ Instructs the compiler to implement full Microsoft compatibility.), печатает всегда А.

А MSVC — B.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[22]: class member access question
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 26.08.04 04:48
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Спасибо, добавил в свою коллекцию багов (да, я энтомолог)


Не за что. IMHO, эта ветка это флейм. А обсуждение бага здесь
Автор: sergey_shandar
Дата: 11.08.04
. Спасибо за еще один пример с private.
getboost.codeplex.com
citylizard.codeplex.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.