Interesting C/C++ interview questions

Yuri_p33
Уже с Приветом
Posts: 394
Joined: 12 Feb 2001 10:01
Location: USA

Post by Yuri_p33 »

ballymahon wrote:
8K wrote:Неужели нельзя "запечатать" класс собственными средствами С++? Не верю.
А как интересно? Можно конечно не использовать виртуальных функций и protected членов (о чем уже упоминалось) и тогда от наследования не будет особого толку, хотя сама возможность и будет присутствовать.
Как запретить наследование от данного класса - разве что сделать все конструкторы приватными и создавать обьекты статической функцией?
Примерно так:

Code: Select all

class Final
{
protected:
   Final(int) {}
};

class MySealedClass: private virtual Final
{
public:
   MySealedClass(): Final(0) {};
   /* your code */
};

class MyDerivedClass: public MySealedClass
{
};

Хотя этот код скомпилируется, при попытке создать переменную типа MyDerivedClass компилятор пошлет нас подальше. Говорят, такой вопрос даже на интервью бывает :)
User avatar
шпиён
Уже с Приветом
Posts: 3459
Joined: 29 Oct 2002 20:08
Location: US

Post by шпиён »

interrupt wrote: virtual ~IMyInterface() = 0


Do not do that, dude.
interrupt
Уже с Приветом
Posts: 4022
Joined: 08 Dec 1999 10:01
Location: USA <-> Moscow

Post by interrupt »

шпиён wrote:
interrupt wrote: virtual ~IMyInterface() = 0


Do not do that, dude.


Вопрос, почему??
interrupt
Уже с Приветом
Posts: 4022
Joined: 08 Dec 1999 10:01
Location: USA <-> Moscow

Post by interrupt »

2 Yuri_p33: Прикольная конструкция :) Как работает - из кода сразу понятно, но вот не встречал такого. Благодарствую!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

Yuri_p33 wrote:
ballymahon wrote:
8K wrote:Неужели нельзя "запечатать" класс собственными средствами С++? Не верю.
А как интересно? Можно конечно не использовать виртуальных функций и протецтед членов (о чем уже упоминалось) и тогда от наследования не будет особого толку, хотя сама возможность и будет присутствовать.
Как запретить наследование от данного класса - разве что сделать все конструкторы приватными и создавать обьекты статической функцией?
Примерно так:

Code: Select all

цласс Финал
{
протецтед:
   Финал(инт) {}
};

цласс МыСеаледЦласс: привате виртуал Финал
{
публиц:
   МыСеаледЦласс(): Финал(0) {};
   /* ыоур цоде */
};

цласс МыДериведЦласс: публиц МыСеаледЦласс
{
};

Хотя этот код скомпилируется, при попытке создать переменную типа МыДериведЦласс компилятор пошлет нас подальше. Говорят, такой вопрос даже на интервью бывает :)


Шо-шо? А если самому попробовать откомпилить и переменную создать?
Верить нельзя никому - даже себе. Мне - можно!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

interrupt wrote:2 Юри_п33: Прикольная конструкция :) Как работает - из кода сразу понятно, но вот не встречал такого. Благодарствую!

Мне расскажите как работает - мне непонятно. Ни сразу, ни потом. :mrgreen: :mrgreen:
Верить нельзя никому - даже себе. Мне - можно!
interrupt
Уже с Приветом
Posts: 4022
Joined: 08 Dec 1999 10:01
Location: USA <-> Moscow

Post by interrupt »

A. Fig Lee wrote:
interrupt wrote:2 Юри_п33: Прикольная конструкция :) Как работает - из кода сразу понятно, но вот не встречал такого. Благодарствую!

Мне расскажите как работает - мне непонятно. Ни сразу, ни потом. :mrgreen: :mrgreen:


А вы в код всмотритесь - вы же спец по С++ :)

Сам бы я до такой конструкции наверное не додумался бы. Но написанный код - ясен и понятен...
User avatar
шпиён
Уже с Приветом
Posts: 3459
Joined: 29 Oct 2002 20:08
Location: US

Post by шпиён »

interrupt wrote:
шпиён wrote:
interrupt wrote: virtual ~IMyInterface() = 0


Do not do that, dude.


Вопрос, почему??


Тело должно быть, иначе наследному дестрактору нечего вызывать.
interrupt
Уже с Приветом
Posts: 4022
Joined: 08 Dec 1999 10:01
Location: USA <-> Moscow

Post by interrupt »

шпиён wrote:
interrupt wrote:
шпиён wrote:
interrupt wrote: virtual ~IMyInterface() = 0


Do not do that, dude.


Вопрос, почему??


Тело должно быть, иначе наследному дестрактору нечего вызывать.



Хм, я же вроде прописал там:

Code: Select all

virtual ~MyInterface() = 0 {   }


если вы это имели в виду?
User avatar
WPooh
Уже с Приветом
Posts: 292
Joined: 22 Jul 2002 04:03
Location: Vl->Nsk->SFBA

Post by WPooh »

A. Fig Lee wrote:Мне расскажите как работает - мне непонятно. Ни сразу, ни потом. :mrgreen: :mrgreen:

Мне тоже непонятно было сразу.
[q=Страуструп Б., Язык программирования С++, 3 издание, 15.2.4.1]
Конструктор виртуального базового класса вызывается (явно или неявно) из конструктора объекта (конструктора самого "нижнего" производного класса).
[/q]

Успехов!
Работа освобождает.
Vovka
Уже с Приветом
Posts: 1906
Joined: 14 Mar 2001 10:01

Post by Vovka »

ballymahon wrote:
8K wrote:
uncle_Pasha wrote:
yocto wrote:
uncle_Pasha wrote:Если класс не задумывался как базовый, почему бы не использовать struct?

Так ведь объявление типа через struct не запрещает наследование.

Оно объясняет смысл данного элемента данных.
99% что никому не прийдет в голову наследоваться от struct в дальнейшем

Неужели нельзя "запечатать" класс собственными средствами С++? Не верю.


А как интересно? Можно конечно не использовать виртуальных функций и protected членов (о чем уже упоминалось) и тогда от наследования не будет особого толку, хотя сама возможность и будет присутствовать.
Как запретить наследование от данного класса - разве что сделать все конструкторы приватными и создавать обьекты статической функцией?


На самом деле, даже не наследование запрещать надо, а удаление через указатель на базовый класс.

А для этого достаточно сделать _невитруальный_ деструктор protected.
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

interrupt wrote:
A. Fig Lee wrote:
interrupt wrote:2 Юри_п33: Прикольная конструкция :) Как работает - из кода сразу понятно, но вот не встречал такого. Благодарствую!

Мне расскажите как работает - мне непонятно. Ни сразу, ни потом. :мргреен: :мргреен:


А вы в код всмотритесь - вы же спец по С++ :)

Сам бы я до такой конструкции наверное не додумался бы. Но написанный код - ясен и понятен...

Да? Ну почему у меня все компилируется и дерайвится? Может у меня компайлер неправильный? Вы хоть попробовали компилить ето?
Верить нельзя никому - даже себе. Мне - можно!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

WPooh wrote:
A. Fig Lee wrote:Мне расскажите как работает - мне непонятно. Ни сразу, ни потом. :мргреен: :мргреен:

Мне тоже непонятно было сразу.
[q=Страуструп Б., Язык программирования С++, 3 издание, 15.2.4.1]
Конструктор виртуального базового класса вызывается (явно или неявно) из конструктора объекта (конструктора самого "нижнего" производного класса).
[/q]

Успехов!

Оооо..! Теперь мне понятно, что вам неправильно понятно. :mrgreen: :mrgreen: Виртуальный класс - ну и ? Наследовать то я все равно могу. Да, нельзя сделать обьект оф деривед класс ЕСЛИ КАК МИНИМУМ 1 ОБЙЕКТ парента УЖЕ присутствует в системе. Но ето НИКАК не запрещает мне наследовать свои классы.
Верить нельзя никому - даже себе. Мне - можно!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

Vovka wrote:
ballymahon wrote:
8K wrote:
uncle_Pasha wrote:
yocto wrote:
uncle_Pasha wrote:Если класс не задумывался как базовый, почему бы не использовать струцт?

Так ведь объявление типа через струцт не запрещает наследование.

Оно объясняет смысл данного элемента данных.
99% что никому не прийдет в голову наследоваться от струцт в дальнейшем

Неужели нельзя "запечатать" класс собственными средствами С++? Не верю.


А как интересно? Можно конечно не использовать виртуальных функций и протецтед членов (о чем уже упоминалось) и тогда от наследования не будет особого толку, хотя сама возможность и будет присутствовать.
Как запретить наследование от данного класса - разве что сделать все конструкторы приватными и создавать обьекты статической функцией?


На самом деле, даже не наследование запрещать надо, а удаление через указатель на базовый класс.

А для этого достаточно сделать _невитруальный_ деструктор протецтед.

Ну все, дожились. За что боролись, на то и напоролись. Страуструп думал-думал всюночь, наверное. Придумал. Пришел Вовка и все почикал. :mrgreen: Ееее... Есь такой хороший язык - С называется или Ява - там тоже много чего почикано. Рекомендую.
Верить нельзя никому - даже себе. Мне - можно!
User avatar
шпиён
Уже с Приветом
Posts: 3459
Joined: 29 Oct 2002 20:08
Location: US

Post by шпиён »

interrupt wrote:Хм, я же вроде прописал там:

Code: Select all

virtual ~MyInterface() = 0 {   }


если вы это имели в виду?


Сорри, скобочек не заметил.
Так в чем пойнт =0 тогда?
Vovka
Уже с Приветом
Posts: 1906
Joined: 14 Mar 2001 10:01

Post by Vovka »

A. Fig Lee wrote:
Vovka wrote:
ballymahon wrote:
8K wrote:
uncle_Pasha wrote:
yocto wrote:
uncle_Pasha wrote:Если класс не задумывался как базовый, почему бы не использовать струцт?

Так ведь объявление типа через струцт не запрещает наследование.

Оно объясняет смысл данного элемента данных.
99% что никому не прийдет в голову наследоваться от струцт в дальнейшем

Неужели нельзя "запечатать" класс собственными средствами С++? Не верю.


А как интересно? Можно конечно не использовать виртуальных функций и протецтед членов (о чем уже упоминалось) и тогда от наследования не будет особого толку, хотя сама возможность и будет присутствовать.
Как запретить наследование от данного класса - разве что сделать все конструкторы приватными и создавать обьекты статической функцией?


На самом деле, даже не наследование запрещать надо, а удаление через указатель на базовый класс.

А для этого достаточно сделать _невитруальный_ деструктор протецтед.

Ну все, дожились. За что боролись, на то и напоролись. Страуструп думал-думал всюночь, наверное. Придумал. Пришел Вовка и все почикал. :mrgreen: Ееее... Есь такой хороший язык - С называется или Ява - там тоже много чего почикано. Рекомендую.


Пошто имя трупово всуе употребляете? :mrgreen:

В с чем несогласны-то?
Действительно, наследовать от класса с невиртуальным деструктором можно. Удалять через указатель на базовый - нельзя. Для того, чтобы это предотвратить - делаем деструктор базового класса protected. Чего тут неясно? :pain1:
User avatar
WPooh
Уже с Приветом
Posts: 292
Joined: 22 Jul 2002 04:03
Location: Vl->Nsk->SFBA

Post by WPooh »

A. Fig Lee wrote:Оооо..! Теперь мне понятно, что вам неправильно понятно. :mrgreen: :mrgreen: Виртуальный класс - ну и ? Наследовать то я все равно могу. Да, нельзя сделать обьект оф деривед класс ЕСЛИ КАК МИНИМУМ 1 ОБЙЕКТ парента УЖЕ присутствует в системе. Но ето НИКАК не запрещает мне наследовать свои классы.

Нет в C++ ключевого слова sealed, это не C#. Насколько я знаю, не подразумевался Страуструпом обрыв цепочки наследования при разработке C++. Поправьте меня, если я не прав.
Поэтому, вы можете сколько угодно наследоваться от какого угодно класса. Экземпляр получить можете не всегда. Иногда это имеет смысл, иногда - нет.
Мой комментарий касался того, что объект не сможет быть сконструирован.
То есть, как ответ на:
A. Fig Lee wrote:Шо-шо? А если самому попробовать откомпилить и переменную создать?

A. Fig Lee wrote:Мне расскажите как работает - мне непонятно. Ни сразу, ни потом.

Идет за ответ?

A. Fig Lee wrote:Да, нельзя сделать обьект оф деривед класс ЕСЛИ КАК МИНИМУМ 1 ОБЙЕКТ парента УЖЕ присутствует в системе.

Объект родителя тут при чем? Вот тут уж мне не понятно. Мы про паттерн single instance говорим? :pain1: Объясните мысль, пожалуйста.
Работа освобождает.
Yuri_p33
Уже с Приветом
Posts: 394
Joined: 12 Feb 2001 10:01
Location: USA

Post by Yuri_p33 »

A. Fig Lee wrote:
Yuri_p33 wrote:цласс Финал
{
протецтед:
Финал(инт) {}
};

цласс МыСеаледЦласс: привате виртуал Финал
{
публиц:
МыСеаледЦласс(): Финал(0) {};
/* ыоур цоде */
};

цласс МыДериведЦласс: публиц МыСеаледЦласс
{
};[/code]
Хотя этот код скомпилируется, при попытке создать переменную типа МыДериведЦласс компилятор пошлет нас подальше. Говорят, такой вопрос даже на интервью бывает :)
Шо-шо? А если самому попробовать откомпилить и переменную создать?
Пробовал на VC++.NET и ранее на VC++ 6. Работает (т.е. не работает :) )

Code: Select all

int _tmain(int argc, _TCHAR* argv[])
{
   MyDerivedClass a; //Error C2512: 'Final::Final' : no appropriate default constructor available
   return 0;
}
А на каком компиляторе у вас это работает?
TLK
Уже с Приветом
Posts: 305
Joined: 09 Feb 2001 10:01
Location: Nizhniy Novgorod -> MD

Post by TLK »

шпиён wrote:
TLK wrote:Class can be specifically designed to be derived and still leave long healthy life without virtual destructor. And often live well without any destructor at all.
The first example is "pure" interface definition.


This particular example is when the destructor MUST be virtual. (No, I am not a proponen of writing virtual anything by default).


I actually disagree that it "MUST" automatically.
Sometimes it is still not necessary.

Take a look at IUnknown defition its the most basic root interface in COM.
Declared in unknwn.h
No virtual destructor. Of course maybe COM can be considered as a "special case" because in COM we do not "delete" objects but still...
Bst.Rgds.TLK.
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

Vovka wrote:В с чем несогласны-то?
Действительно, наследовать от класса с невиртуальным деструктором можно. Удалять через указатель на базовый - нельзя. Для того, чтобы это предотвратить - делаем деструктор базового класса протецтед. Чего тут неясно? :паин1:

Дык, полиморфизм - неотьемлемая часть языка. То, что вы предлагаете - кастрирование. ИМХО.
Верить нельзя никому - даже себе. Мне - можно!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

WPooh wrote: Объясните мысль, пожалуйста.

Обьясняю: ошибся. сорри... И Плейшнер вывалился из окна. :mrgreen:
Верить нельзя никому - даже себе. Мне - можно!
User avatar
A. Fig Lee
Уже с Приветом
Posts: 12072
Joined: 17 Nov 2002 03:41
Location: английская колония

Post by A. Fig Lee »

Yuri_p33 wrote:А на каком компиляторе у вас это работает?

Nashel oshibku. :?
Верить нельзя никому - даже себе. Мне - можно!
отточие
Posts: 11
Joined: 25 Jan 2003 06:21

Post by отточие »

Yuri_p33 wrote:
A. Fig Lee wrote:
Yuri_p33 wrote:

Code: Select all

class Final 
{
protected:
   Final(int) {}
};

class MySealedClass: private virtual Final
{
public:
   MySealedClass(): Final(0) {};
   /* your code */
};

class MyDerivedClass: public MySealedClass
{
};

Хотя этот код скомпилируется, при попытке создать переменную типа MyDerivedClass компилятор пошлет нас подальше. Говорят, такой вопрос даже на интервью бывает :)
Шо-шо? А если самому попробовать откомпилить и переменную создать?
Пробовал на VC++.NET и ранее на VC++ 6. Работает (т.е. не работает :) )

Code: Select all

int _tmain(int argc, _TCHAR* argv[])
{
   MyDerivedClass a; //Error C2512: 'Final::Final' : no appropriate default constructor available
   return 0;
}
А на каком компиляторе у вас это работает?


Code: Select all

int main(int argc, char **argv, char **envp)
{
    MyDerivedClass a;
    exit(0);
}


gcc/Solaris: "Работает (т.е. не работает :) )" (c)

Code: Select all

  gcc hello.cpp
  hello.cpp: In method `MyDerivedClass::MyDerivedClass()':
  hello.cpp:22: no matching function for call to `Final::Final ()'
  hello.cpp:7: candidates are: Final::Final(int)
  hello.cpp:8:                 Final::Final(const Final &)


GreenHills standard C++ : "Работает (т.е. не работает :) )" (c)

Code: Select all

  "C:\GHS\MyProjects\Project2\src\hello.cpp", line 17: error: no default
            constructor exists for class "Final"
    class MyDerivedClass: public MySealedClass
                               ^
            detected during implicit generation of
                      "MyDerivedClass::MyDerivedClass()" at line 22
  Error: build failed
  Build terminated
  Build failed


GreenHills Embedded C++: Stupid test, as Embedded C++ does not support multiple or virtual inheritance, but nevertheless...
"Работает (т.е. не работает :) )" (c)

Code: Select all

  "C:\GHS\MyProjects\Project2\src\hello.cpp", line 10: error: Embedded C++ does
            not support multiple or virtual inheritance
    class MySealedClass: private virtual Final
                         ^
  "C:\GHS\MyProjects\Project2\src\hello.cpp", line 17: error: no default
            constructor exists for class "Final"
    class MyDerivedClass: public MySealedClass
                                 ^
            detected during implicit generation of
                      "MyDerivedClass::MyDerivedClass()" at line 22
  Error: build failed
  Build terminated
  Build failed
Vovka
Уже с Приветом
Posts: 1906
Joined: 14 Mar 2001 10:01

Post by Vovka »

A. Fig Lee wrote:
Vovka wrote:В с чем несогласны-то?
Действительно, наследовать от класса с невиртуальным деструктором можно. Удалять через указатель на базовый - нельзя. Для того, чтобы это предотвратить - делаем деструктор базового класса протецтед. Чего тут неясно? :паин1:

Дык, полиморфизм - неотьемлемая часть языка. То, что вы предлагаете - кастрирование. ИМХО.


Бог с вами, я, да чтоб предлагал _такое_?! 8O

Я не предлагаю чего-то убирать из языка, я предлагаю - если делаете невиртуальный деструктор в базовом классе, то лучше его сделать protected.
User avatar
WPooh
Уже с Приветом
Posts: 292
Joined: 22 Jul 2002 04:03
Location: Vl->Nsk->SFBA

Post by WPooh »

A. Fig Lee wrote:Обьясняю: ошибся. сорри... И Плейшнер вывалился из окна. :mrgreen:

Ничего, бывает. Image
Работа освобождает.

Return to “Работа и Карьера в IT”