LINUX.ORG.RU

С++, запрет на использование функции родителя


0

0

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

например:


class Parent {
  public:
    virtual void f(); // эта функция обязательно должна быть преропределена!
    virtual void g();
    virtual void h(); // эта функция обязательно должна быть преропределена!
};

class Child : public Parent {
  public:
    virtual void f();
};

....

int main{}
{
  Child *c = new Child();
  c->f(); // это должно работать
  c->g(); // это должно работать
  c->h(); // а это вызывать ошибку компилляции
}

★★

сделай её чисто виртуальной

jtootf ★★★★★
()

Это-то понятно, но я хитрый и хочу создавать и объекты типа Parent тоже.

octy ★★
() автор топика
Ответ на: комментарий от octy

Собственно я сделал Parent1 абстрактным, а наследование через промежуточного родителя Parent, но думал может я что-то не знаю.

octy ★★
() автор топика
Ответ на: комментарий от octy
class Base
{
public:
    virtual void f() {}
    virtual void g() {}
};

class IAux
{
private:
    virtual void g() = 0;
    virtual void f() = 0;
};

class Derived : public Base, IAux
{
public:
    virtual void g() {}
};

но это пятиногий конь, вообще говоря. правильный ответ такой, что ты не должен этого хотеть

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

в IAux функции, которые должны быть переопределены

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

Спасибо ) Но я просто хотел "если я в будущем буду наследовать от этого класса, то не забыть переопределить функцию f()"

Ну например в родителе есть массив переменных типа int, и функция в которой выделяется память для этого массива. Может оказаться, что в потомке массив будет переопределён с типом long, ну и память надо будет выделять в переопределённой функции. int и long - просто для примера, скорее в предке будет массив типа A, а в потомке - массив из потомоков A.

octy ★★
() автор топика
Ответ на: комментарий от jtootf

Уф ).

Ну представь себе класс "ИсследованныеОбъекты", в котором есть массив из объектов типа "ЭлементарнаяЧастица". У объекта "ЭлементарнаяЧастица" есть много свойств: масса, заряд и т.д. И всех всё замечательно устраивает, все этим пользуются, и вдруг у частицы открывают новое свойство. Создаётся класс-потомок "НоваяЭлементарнаяЧастица". Соответственно надо вносить изменения в "ИсследованныеОбъекты": переопределить массив на тип "НоваяЭлементарнаяЧастица", добавить несколько новых функций. И переопределить все те, для которых критично что массив был именно типа "ЭлементарныеЧастица": например, выделяющие память.

octy ★★
() автор топика
Ответ на: комментарий от octy
class IObjects {};

template<typename T>
class Objects : public IObjects
{
private:
    std::vector<T> particles_;
};

в специализации шаблона описываются функции, чья реализация зависит от интерфейса типа T (частиц); выделение памяти к ним не относится

jtootf ★★★★★
()
Ответ на: комментарий от octy

че-то ты невнятное рассказал

но можно определить чистую виртуальную функцию с телом, чтобы потом ее вызывать в потомках

The pure virtual function declaration provides only the prototype of the method. Although an implementation of the pure virtual function is typically not provided in an abstract class, it may be included, although the definition may not be included at the point of declaration [1]. Every non-abstract child class is still required to override the method, but the implementation provided by the abstract class may be called in this way:

class Abstract {
public:
   virtual void pure_virtual() = 0;
};


void Abstract::pure_virtual() {
  // do something
}
 
class Child : public Abstract {
  virtual void pure_virtual(); // no longer abstract, this class may be
                               // instantiated.
};
 
void Child::pure_virtual() {
  Abstract::pure_virtual(); // the implementation in the abstract class 
                            // is executed
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от jtootf

> в специализации шаблона описываются функции, чья реализация зависит от интерфейса типа T (частиц); выделение памяти к ним не относится

вполне возможно топикстартеру нужны именно шаблоны, но я на всякий случай рассказал, как дать чистой виртуальной функции тело

www_linux_org_ru ★★★★★
()

> c->h(); // а это вызывать ошибку компилляции

ммм... скорее всего тебя не дадут уже Child *c = new Child();

да и вообще, что за странное выделение объекта в куче?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от octy

> А что не так с созданием объекта в куче?

м.б. в данном примере оно смотрится странно, а если бы было return c; или Parent* c = new Child(); то смотрелось бы более понятно, впрочем, это все фигня.

www_linux_org_ru ★★★★★
()

>Т.е. я хочу убедиться, что некая функция в классе-потомке обязательно была переопределена

Внутри этой функции проверяй свой фактический тип через RTTI. Если не совпадает - падай через assert. А статическая фагготрия породит больше проблем в организации проекта чем решит.

Absurd ★★★
()
Ответ на: комментарий от octy

Очень плохо продуман дизайн имхо. И RTTI тут - костыль. То, что вполне логично проверять в compile time переносить на RTTI из-за плохого дизайна - вот это фагготрия.

ratatosk
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.