Output
От: Аноним  
Дата: 03.07.08 19:12
Оценка: -1
Что распечатает следующий код:
#include "stdio.h"
#include "conio.h"

class A
{
public:
    A() {printf( "constructor A\n");}
    A(const A & obj){ printf("copy constructor A\n"); }
        ~A() { printf("destructor A\n"); }
    virtual ~A() { printf("destructor A\n"); }
    virtual void fun1() { printf("fun1 A\n"); }
    void fun2(A obj) { printf("fun2 A\n"); }
};
class B: virtual public A
{
public:
    B(){ printf("constructor B\n"); }
    ~B(){ printf("destructor B\n"); }

};
class C: virtual public A
{
public:
    C(){ printf("constructor C\n"); }
    ~C(){ printf("destructor C\n"); }
    void fun1() { printf("fun1 C\n"); }

};
class D :  public B,  public C
{
public:
        D(){ printf("constructor D\n"); }
        ~D(){ printf("destructor D\n"); }
        void fun1(){ printf("fun1 D\n"); }
        void fun2(){ printf("fun2 D\n"); }

};

void main()
{
A * ptr;
A one;
ptr = new D();
ptr ->fun1();
ptr ->fun2(one);
delete ptr;
getch();
}
Re: Output
От: Were  
Дата: 03.07.08 19:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что распечатает следующий код:


Компилятора под рукой нет?
Re: Output
От: Аноним  
Дата: 03.07.08 19:22
Оценка:
Извените, код с ошибкой, должно быть так:
#include "stdio.h"
#include "conio.h"

class A
{
public:
    A() {printf( "constructor A\n");}
    A(const A & obj){ printf("copy constructor A\n"); }

    virtual ~A() { printf("destructor A\n"); }
    virtual void fun1() { printf("fun1 A\n"); }
    void fun2(A obj) { printf("fun2 A\n"); }
};
class B: virtual public A
{
public:
    B(){ printf("constructor B\n"); }
    ~B(){ printf("destructor B\n"); }

};
class C: virtual public A
{
public:
    C(){ printf("constructor C\n"); }
    ~C(){ printf("destructor C\n"); }
    void fun1() { printf("fun1 C\n"); }

};
class D :  public B,  public C
{
public:
        D(){ printf("constructor D\n"); }
        ~D(){ printf("destructor D\n"); }
        void fun1(){ printf("fun1 D\n"); }
        void fun2(){ printf("fun2 D\n"); }

};

void main()
{
A * ptr;
A one;
ptr = new D();
ptr ->fun1();
ptr ->fun2(one);
delete ptr;
getch();
}
Re: Output
От: Vain Россия google.ru
Дата: 03.07.08 19:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что распечатает следующий код:

Насколько помню, сначало вызываются конструкторы виртуальных баз, потом обычных. Деструкторы, соответственно, наоборот. Вы об этом спрашиваете?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: Output
От: Аноним  
Дата: 03.07.08 19:28
Оценка:
V>Насколько помню, сначало вызываются конструкторы виртуальных баз, потом обычных. Деструкторы, соответственно, наоборот. Вы об этом спрашиваете

Понимаете, сегодня из 30 собеседуемых, на этот вопрос правильно ответоло только двое. Неужели он такой трудный?
Re[3]: Output
От: Erop Россия  
Дата: 03.07.08 19:35
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Понимаете, сегодня из 30 собеседуемых, на этот вопрос правильно ответоло только двое. Неужели он такой трудный?


Зависит от того, какой ответ считать верным...
Если, например, такой: "А фиг его знает. Конечно базы объектов всегда создадутся раньше всех своих наследников, но конкретный порядок вызовов конструкторв я вам не скажу, так как код, который зависит от этого порядка, уж простите, не пишу", то не трудный. Правда не понятно на кой его задавать
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Топики лучше называть правильно...
От: Erop Россия  
Дата: 03.07.08 19:37
Оценка: +1
Например этот хорошо бы назвать както так: "Неужели я задаю на собеседовании плохие вопросы?" или, хотя бы, както так: "Хороший ли это вопрос для собеседования?"...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Output
От: Аноним  
Дата: 03.07.08 19:53
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>Понимаете, сегодня из 30 собеседуемых, на этот вопрос правильно ответоло только двое. Неужели он такой трудный?


E>Зависит от того, какой ответ считать верным...

E>Если, например, такой: "А фиг его знает. Конечно базы объектов всегда создадутся раньше всех своих наследников, но конкретный порядок вызовов конструкторв я вам не скажу, так как код, который зависит от этого порядка, уж простите, не пишу", то не трудный. Правда не понятно на кой его задавать

Я тоже пользуюсь STL, но простите, связаный список писать надо ументь, даже если мы и не делаем этого каждый день.
Не согласны?
Re[5]: Таки надо для чего? :)
От: Erop Россия  
Дата: 03.07.08 20:01
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>Я тоже пользуюсь STL, но простите, связаный список писать надо ументь, даже если мы и не делаем этого каждый день.

А>Не согласны?

Я согласен, что слово "надо" подразумевает так же наличие ответа на вопрос "для чего надо?".
Соответсвенно для чего надо уметь реализовывать связанный список я могу предположить, хотя у этого "надо уметь" очень даже широкие границы, между прочим.

Но вот для чего надо точно знать порядок конструирования виртуальных и невиртуальных баз я, например, не знаю. Я, наоборот, считаю, что код, который полагается на такого рода знания -- кривой. IMHO ничего, кроме утверждения "на момент вызова конструктора объекта все его бызы и поля уже сконструированы" использовать не стоит... Хотя занть может быть и не вредно.


Но это всё офтоп. Ты спросил сложен ли этот вопрос. Я тебе ответил, в какой редакции требуемого ответа он, IMHO, не слишком сложен...
Правда зачем его задавать мне было бы интересно узнать. Непомредмтвенной связи с умением писать списки произвольной связанности я пока не осознал...

Кстати, STL я использую ТОЛЬКО в демках, сэмплах, некоторых утилитах и прочем некоммерческом коде
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Output
От: oziro Нигерия  
Дата: 03.07.08 20:08
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Я тоже пользуюсь STL, но простите, связаный список писать надо ументь, даже если мы и не делаем этого каждый день.

А>Не согласны?

Если имеется ввиду тот список, что пишут обычно на часовой лабе в универе — то уметь надо, но это не целесообразно на собеседовании (хотя, смортя какая вакансия). Такой код обычно никуда не годен, как минимум не оттестирован.

Уметь писать полноценный библиотечный контейнер на собеседовании, на коленке ИМХО не нужно.

А вот про сложность ( O ) операций с контейнерами нужно знать, про способы сделать контейнер обобщенным, про удобный интерфейс контейнера, про thread-safe...

Сорри что вклинился в разговор
Re[2]: Output
От: Аноним  
Дата: 04.07.08 04:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Извените, код с ошибкой, должно быть так:

...
Извините, но код все еще с ошибкой — 'int main()'. Я понимаю, что это выглядит как придирка с моей стороны, но раз уж вопрос касается нетривиальных моментов языка, то 'void main()' рядом, imho, смотрится стремно.

#dogma int main (c)c.l.c.m.
Re[3]: Output
От: Аноним  
Дата: 04.07.08 08:13
Оценка: -1
Это скорее дело хорошего или плохого стиля, но никак не ошибка.
Re: Output
От: GGoga  
Дата: 04.07.08 08:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что распечатает следующий код:

А>//...

Чисто ради спортивного интереса решил "набросать" результат работы данного кода без использования помощи компилятора, получилось следующее:

constructor A
constructor A
constructor B
constructor C
constructor D
fun1 A               // <--- Ошибка была здесь!!!
copy constructor A
fun2 A
destructor A
destructor D
destructor C
destructor B
destructor A
destructor A


Но в результате, запустив приложение на исполнение, убедился, что немного ошибся Решил спросить, почему в этом месте (указанном в виде выделенного комментария) должен был сработать вызов метода D::fun1? После работы приложения интуитивно становится понятно, что дело именно в полиморфизме и для экземпляра класса D и должен вызываться переопределенный в этом классе метод, но все же хотелось бы услышать конкретный ответ экспертов по этому поводу Заранее спасибо!
Re[6]: Таки надо для чего? :)
От: Кодт Россия  
Дата: 04.07.08 09:02
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Но вот для чего надо точно знать порядок конструирования виртуальных и невиртуальных баз я, например, не знаю. Я, наоборот, считаю, что код, который полагается на такого рода знания -- кривой. IMHO ничего, кроме утверждения "на момент вызова конструктора объекта все его бызы и поля уже сконструированы" использовать не стоит... Хотя занть может быть и не вредно.


Для чего это нужно знать:
1) Чтобы не накосячить, если вдруг зависимость от порядка инициализации возникнет.
2) Чтобы сопровождать и отлаживать чужой код, в котором такая зависимость уже существует как данность.

Применение RAII в масштабе большем, чем scope guards — вообще требует повышенной осознанности в вопросах конструкторов-деструкторов.
Двухфазная инициализация — это, конечно, выход, но
— это менее удобно, чем однофазная (больше писанины)
— риск чего-нибудь забыть
— более длительные отрезки времени, когда объект находится в недоделанном состоянии

E>Кстати, STL я использую ТОЛЬКО в демках, сэмплах, некоторых утилитах и прочем некоммерческом коде


Так и запишем: темплейтофобия
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Output
От: DarkTranquillity  
Дата: 04.07.08 09:16
Оценка:
Здравствуйте, Аноним, Вы писали:

V>>Насколько помню, сначало вызываются конструкторы виртуальных баз, потом обычных. Деструкторы, соответственно, наоборот. Вы об этом спрашиваете


А>Понимаете, сегодня из 30 собеседуемых, на этот вопрос правильно ответоло только двое. Неужели он такой трудный?


Считайте, что трое из 30, я тоже ответил.
Но вот действительно, такое глубокое знание С/С++ нужно только там, где четко используется С/С++, не так ли?
Re[7]: Таки надо для чего? :)
От: Erop Россия  
Дата: 04.07.08 09:29
Оценка: -1
Здравствуйте, Кодт, Вы писали:

К>1) Чтобы не накосячить, если вдруг зависимость от порядка инициализации возникнет.

Интересно бы посмотреть на такой код, где это необходимо...

К>2) Чтобы сопровождать и отлаживать чужой код, в котором такая зависимость уже существует как данность.

Ну опять же, надёжнее переделать. Но в любом случае, если у нас очень плохой код надо поддерживать, то вообще нереальный эксперт в С++, платформе и программировании нужен. Так как накосячить, так, чтобы "почти работало" можно очень ОЧЕНЬ многими способами.
Мене таких спецов на поддержку ставить обычно жаба давит
В любом случае это всё очень сильно от целей собеседования зависит...

К>Применение RAII в масштабе большем, чем scope guards — вообще требует повышенной осознанности в вопросах конструкторов-деструкторов.

К>Двухфазная инициализация — это, конечно, выход, но
К>- это менее удобно, чем однофазная (больше писанины)
К>- риск чего-нибудь забыть
К>- более длительные отрезки времени, когда объект находится в недоделанном состоянии

Если вдруг, почему-то, твои RAII умеют конструироваться без параметров (обычно они все умеют, так как должны уметь Close() ), то пишешь не так:
MyObj::MyObj( .. ) : Base1( .. ), Base2( .. ), Field1( .. ), field2( .. ) {}
а так:
MyObj::MyObj( ... )
{
   Base1::Open( ... );
   Base2::Open( ... );
   field1.Open( ... );
   field2.Open( ... );
}

Чем второе хуже первого -- не совсем понятно...

Правда использование в качестве RAII виртуальной базы, да ещё и не с дефолтным конструктором -- тема отдельная и интересная
IMHO ничем, кроме перднамеренного сабатажа это объяснить невозможно

E>>Кстати, STL...

К>...темплейтофобия
Может не будем поднимать старый флейм?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Output
От: Кодт Россия  
Дата: 04.07.08 10:03
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>fun1 A // <--- Ошибка была здесь!!!


GG>Но в результате, запустив приложение на исполнение, убедился, что немного ошибся Решил спросить, почему в этом месте (указанном в виде выделенного комментария) должен был сработать вызов метода D::fun1? После работы приложения интуитивно становится понятно, что дело именно в полиморфизме и для экземпляра класса D и должен вызываться переопределенный в этом классе метод, но все же хотелось бы услышать конкретный ответ экспертов по этому поводу Заранее спасибо!


Да, виртуальная функция переопределена — а при чём здесь "интуитивно"? Это и логически тоже понятно.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Output
От: GGoga  
Дата: 04.07.08 10:09
Оценка:
Здравствуйте, Кодт, Вы писали:

К>...а при чём здесь "интуитивно"? Это и логически тоже понятно.


Просто я всегда думал (теперь уже понимаю, что не правильно!!!), что для переопределения виртуального метода всегда необходимо указывать ключевое слово virtual (по крайней мере, я так всегда делал), а теперь понял и буду знать, что нет
Re[4]: Output
От: Аноним  
Дата: 04.07.08 10:43
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>Здравствуйте, Кодт, Вы писали:


К>>...а при чём здесь "интуитивно"? Это и логически тоже понятно.


GG>Просто я всегда думал (теперь уже понимаю, что не правильно!!!), что для переопределения виртуального метода всегда необходимо указывать ключевое слово virtual (по крайней мере, я так всегда делал), а теперь понял и буду знать, что нет


Тогда думаю, Вам это будет интерессно.
Re[2]: Output
От: Аноним  
Дата: 04.07.08 11:44
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>destructor A

GG>destructor D
GG>destructor C
GG>destructor B
GG>destructor A
GG>destructor A

Складывается впечатление, что Вы пологаете, что в экзепляре класса D существует два объекта А.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.