Pierwszy raz spotykam się z takim problemem, ale spróbuję Ci go naświetlić. Nawiązując do cppreference.com:
A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)
Wywołując funkcję składową method na rzecz obiektu, który siedzi w wektorze children łamiesz w pewnym sensie punkt 2, gdyż wektor zawiera w sobie wskaźniki na obiekty typu (statycznego) Base. A na logikę rzecz biorąc: Base dziedziczy z Base? Nie, bzdura! Oznacza to, że praca na tym obiekcie nie jest możliwa, gdyż jest on niedostępny dla klas dziedziczących. Tu masz jeszcze mój test:
#include <type_traits>
struct Derived1; // fwd
struct Derived2; // fwd
struct Base {
protected:
// Wskaźnik na obiekt klasy bazowej (Base)
Base* foo;
// Wskaźniki na obiekty klas dziedziczących (Derived1, Derived2)
Derived1* foo1;
Derived2* foo2;
// Jakaś wartosć
int value;
virtual void foobar() { }
};
struct Derived1 : public Base {
void foobar() override;
};
struct Derived2 : public Base {
void foobar() override;
};
void Derived1::foobar() {
// Praca nie jest możliwa, decltype(*foo) nie dziedziczy z Base, tylko nią jest.
foo->foobar();
// Typy decltype(*foo1) i decltype(*foo2) dziedziczą z Base, więc praca jest możliwa
foo1->foobar();
foo2->foobar();
using FooType = std::decay_t<decltype(*foo)>;
using Foo1Type = std::decay_t<decltype(*foo1)>;
using Foo2Type = std::decay_t<decltype(*foo2)>;
static_assert(std::is_same<FooType, Base>::value &&
std::is_same<Foo1Type, Derived1>::value &&
std::is_same<Foo2Type, Derived2>::value, "error");
// Błąd wystąpił z powodu !std::is_same<Base, FooType>::value
static_assert(std::is_base_of<Base, FooType>::value && !std::is_same<Base, FooType>::value &&
std::is_base_of<Base, Foo1Type>::value && !std::is_same<Base, Foo1Type>::value &&
std::is_base_of<Base, Foo2Type>::value && !std::is_same<Base, Foo2Type>::value, "error");
// Niejawne użycie this, a decltype(*this) dziedziczy z Base
value = 0;
}
void Derived2::foobar() {
// Patrz wyżej
foo->foobar();
foo1->foobar();
foo2->foobar();
value = 0;
}
Rozwiązaniem może być umieszczenie deklaracji friend w klasie Base.