Tuesday, February 28, 2012

class and struct in C++

Differences between keywords class and struct in C++:
- In absence of an access-specifier for a base class, public is assumed when the derived class is declared struct and private is assumed when the class is declared class;
- Member of a class defined with the keyword class are private by default. Members of a class defined with the keywords struct or union are public by default;
- Keyword class can be used to declare a template parameter, while struct cannot;
- Keyword struct is compatible with C language, while class is not
.

Thursday, November 17, 2011

using namespace

Есть хорошая книга котрую я давно читал – «Стандарты программирования на C++ 101 правило и рекомендация» Герб Саттер, Андрей Александреску. Там была вот такая рекомендация №59: «Не используйте using для пространств имен в заголовочных файлах или перед директивой #include». И вот я заметил, что в коде сгенеренным мастером ATL используется using namespace в *.h:

...
using namespace ATL;

// CNoNamePreview
class ATL_NO_VTABLE CNoNamePreview :
    public CComObjectRootEx< CComSingleThreadModel >,
    public CComCoClass< CNoNamePreview, &CLSID_NoNamePreview >,
    public IObjectWithSiteImpl< CNoNamePreview >,
...

Вроде ничего такого, т.к. этот хедер дальше нигде не должен включатся. Но как-то непривычно что-ли. То что выше относится к MSVS2010sp1, а вот так делал мастер в MSVS2008sp1:

// stdafx.h
...
#define _ATL_NO_AUTOMATIC_NAMESPACE
...
using namespace ATL;
...

Wednesday, November 16, 2011

Custom Deleter - shared_ptr<> vs unique_ptr<>

Раньше можно было делать так:

// shared_ptr< > way
LPWSTR lpName = NULL;
std::tr1::shared_ptr< WCHAR > spName( (
    spItem->GetDisplayName( SIGDN_FILESYSPATH, &lpName ), lpName ),
        CoTaskMemFree );

Теперь можно и вот так:

// unique_ptr< > way
typedef void ( __cdecl* _COM_DELETER )( LPVOID );

LPWSTR lpName = NULL;
std::unique_ptr< WCHAR, _COM_DELETER > spName( (
    spItem->GetDisplayName( SIGDN_FILESYSPATH, &lpName ), lpName ),
        CoTaskMemFree );

В случае с unique_ptr< > нет дополнительного оверхеда на счетчик и проверки-вызова делитера в рантайме, но теперь приходится указывать тип. А ещё можно делать такое:

std::unique_ptr< int[ ] > ar( new int[ 100 ] );

Thursday, May 5, 2011

Virtual inheritance in C++

Часто встречал вопрос на эту тему. Ответ что это и как работает, как бы намекает, что человек как минимум внимательно читает книги (т.к. большинство людей этот вид наследования не используют). Обычно ответ такой: нужно чтоб избежать двух копий базового класса при «ромбовидном» наследовании.
Обычно на этом всё заканчивается – мол, молодец (читаешь внимательно).
Но вопросы нужно продолжить. Например:
– Что если не использовать виртуальное наследование в данном случае? Как тогда?
О:…
– Во всех ли случаях этот вид наследования нужен, если нет, то в каких?
О: Если нет дублирования данных, только функции – то в принципе это дублирование никому не мешает.
– В MS COM есть базовый класс IUnknown, и есть дальше почти всегда «ромбовидное» наследование, но виртуальность тут не используется, почему?
О: Бинарный стандарт COM требует такую структуру в памяти, где у каждого есть своя копия таблицы IUnknown.
– Как выглядит это в памяти, и что со скоростью?
О: ESC_Boston_01_304_paper, страница 19.

Далее после этих вопросов, можно спросить, а зачем вообще нужно наследование? Что делать если его нет? Хорошо или плохо его использовать, почему, когда, где? Очень болезненная тема для многих. Часто в проекте получается, типа один говорит «Не трогайте мои классы/мою архитектуру!», а ему в ответ «OOP must Go!». Вот в тему очень полезная статья/блог: avoiding inheritance dependency