Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Запрет наследования, С++

602
06 мая 2010 года
KPI Student
265 / / 16.12.2006
Скажите, пожалуйста, почему для запрета наследования класса обязательно нужно использовать виртуальное наследование?

Приведу пример, так все ок (то есть, эррор):
Код:
template <class FriendClass>
class nonderivable
{
    friend FriendClass;

private:
    nonderivable() { }
};

class my_class: public virtual nonderivable<my_class>
{
public:
    my_class(){}
};

class DD: public my_class { };

int main()
{
    my_class a;
    DD dd; // error
    return 0;
}


Вроде все понятно. Но зачем именно виртуальное наследование?

Вот такой вариант не катит (то есть, эррора нет):
Код:
template <class FriendClass>
class nonderivable
{
    friend FriendClass;

private:
    nonderivable() { }
};

class my_class: public nonderivable<my_class>
{
public:
    my_class(){}
};

class DD: public my_class { };

int main()
{
    my_class a;
    DD dd;
    return 0;
}


Про закрытое наследование почитал, представление имею, но в этом вопросе, как в советском Ералаше: "понял, что параллельные линии не пересекаются, но не понял, почему" :)
376
06 мая 2010 года
Absolut
220 / / 22.11.2002
Разрешите полюбопытствовать, для каких целей в данном случае используется "friend FriendClass;" ?
3
06 мая 2010 года
Green
4.8K / / 20.01.2000
Убери friend FriendClass; и все будет в норме.
602
06 мая 2010 года
KPI Student
265 / / 16.12.2006
Я, наверное, неправильно выразился где-то.

Суть в чём: я хочу сделать класс my_class так, чтобы от него невозможно было отнаследоваться. Причем так, чтобы не накладывать значимых ограчений на то, как инстанцируются объекты данного класса.

Вижу два пути:
1. Прайват конструктор-деструтор. Этот путь отпадает, так как накладывает существенные ограничения на создание объекта.

Код:
class my_class
{
private:
    my_class();
public:
    ...
};

int main()
{
    my_class a; // error
    my_class* p = new my_class; // error
    std::vector<my_class> v; // error

    my_class* b = my_class::createInstance(); // ок, но зачем так неудобно?

    return 0;
}


Второй способ: отнаследовать my_class от класса с прайват-конструктором. Для обеспечения возможности создавать экземпляры my_class делаем его френдом к базовому классу. За счет того, что дружественность не передается ни потомкам, ни друзьям друзей, получаем нужный результат.

Код:
class nonderivable
{
    friend my_class;

private:
    nonderivable() { }
};

class my_class: public virtual nonderivable
{
public:
    my_class(){}
};
Вроде все ок, но хардкодинг имени класса в базовый класс (nonderivable) не есть гуд. Чуть улучшаю:
Код:
template <class FriendClass>
class nonderivable
{
    friend FriendClass;

private:
    nonderivable() { }
};

class my_class: public virtual nonderivable<my_class>
{
public:
    my_class(){}
};

int main()
{
    my_class a; // ok
    my_class* p = new my_class; // ok
    std::vector<my_class> v; // ok

    class B : public my_class {};
    B illegalObject; // error - то, что и нужно было получить

    return 0;
}


Собственно, вопрос - зачем здес виртуальное наследование? Я думал, что незачем, но без него последней и нужной ошибки не наблюдается.
Отсюда еще вопрос: почему при виртуальном наследовании нельзя создать экземпляр класса B, а при невиртуальном - можно?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог