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;
}
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;
}
Про закрытое наследование почитал, представление имею, но в этом вопросе, как в советском Ералаше: "понял, что параллельные линии не пересекаются, но не понял, почему" :)
Разрешите полюбопытствовать, для каких целей в данном случае используется "friend FriendClass;" ?
Убери friend FriendClass; и все будет в норме.
Суть в чём: я хочу сделать класс 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;
}
{
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(){}
};
{
friend my_class;
private:
nonderivable() { }
};
class my_class: public virtual nonderivable
{
public:
my_class(){}
};
Код:
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;
}
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, а при невиртуальном - можно?