powiedzmy, że mamy następującą hierarchię:Jak zapobiegać wezwanie do wdrożenia podstawowej metody
class Abstract
{
public:
virtual void foo() = 0;
};
class Base : public Abstract
{
public:
virtual void foo() override; //provides base implementation
};
class Derived : public Base
{
public:
virtual void foo() override; //provides derived implementation
};
Jeśli Base::foo()
kiedykolwiek nazywa na obiekcie Derived
że obiekt będzie utratę synchronizacji, a jego dane zostaną uszkodzone. Dziedziczy on strukturę danych i jej manipulację, ale musi wykonać dodatkowe operacje, dlatego wywołanie tylko tych Base::foo()
spowoduje pominięcie tych dodatkowych operacji, w wyniku czego stan Derived
zostanie uszkodzony.
Dlatego chciałbym uniknąć bezpośredniego połączenia z Base
realizacji foo
więc to:
Derived d;
d.Base::foo();
idealnie, powinien dać mi błąd czasu kompilacji niektórych rodzajów. Lub nie rób nic lub w inny sposób można temu zapobiec.
Jednak może to być ja naruszające zasady polimorfizmu i powinno zamiast użyć kompozycję ale to wymagałoby dużo dodatkowego typowania ...
Coś nie tak z 'protected:' zamiast 'public:' dla tej metody w 'Base'?I fwiw, to także wydaje się przyzwoitym kandydatem do redeclarowania jako czysto-wirtualnego w 'Bazie' * i * dostarczaniu implementacji' Base', która nie jest powszechna, ale ma miejsce. Jeśli 'Derived' powinno * zawsze * być zaimplementowane, wydaje się, że przyzwoicie pasuje. – WhozCraig
@WhozCraig Nie wiedziałem, że mogę zapewnić implementację dla czystej wirtualnej metody. Czy to uniemożliwia wywoływanie tej implementacji, jeśli została ona ponownie zaimplementowana przez osoby, które ją dziedziczą? – Resurrection
@Resurrection nie, dlatego 'chronione' na' Base :: foo' wejdzie. Ale to, co * robi *, to wymuszenie klas pochodnych, aby nadal zapewniały przesłonięcia, jednocześnie zapewniając wspólną implementację Base, którą mogą wywołać bez podrzucania dodatkowa funkcja członka do złego samopoczucia. – WhozCraig