Template, dziedziczenie - reference is ambiguos

0

Witam.

Mam sobie template InstancesController, który posiada parę metod statycznych. Służy on do kontrolowania liczebności utworzonych instancji klasy.

template<class T>
class InstancesController
{
	public:
		InstancesController() ;
		virtual ~InstancesController() ;

		static const unsigned getNumberOfInstances() ;
		static const unsigned getNextIndex() ;
		static InstancesController<T> *getInstance(unsigned index) ;
		static void clear() ;
	private:
		static std::map<unsigned, InstancesController<T>*> instances ;
		static unsigned nextIndex ;
		const unsigned index ;
};

Mam też 2 testowe klasy:

	class A : public InstancesController<A>
	{
		public:
			A(){}
			virtual ~A(){}
	};


	class B : public InstancesController<B>, protected A
	{
		public:
			B(){}
			virtual ~B(){}
	};

gdy w testach chcę wywołać np. B::clear() dostaję:

test/suite/InstancesControllerTest.cpp: In member function ‘virtual void<unnamed>::InstancesController_DerivingTest_Test::TestBody()’:
test/suite/InstancesControllerTest.cpp:70: error: reference to ‘clear’ is ambiguous
src/tools/InstancesController.h:84: error: candidates are: static void InstancesController<T>::clear() [with T = InstancesControllerHelpers::A]
src/tools/InstancesController.h:84: error:                 static void InstancesController<T>::clear() [with T = InstancesControllerHelpers::B]

Właściwie czemu? Przecież B dziedziczy po A protected, więc z poziomu testu A::clear() nie powinno być widoczne...

Dzięki za wszelkie podpowiedzi

0

a spróbuj:
InstancesController<B>::clear();

0

no tak działa. ale właśnie chciałem zrobić to szybko poprzez dziedziczenie, aby odwoływać się przez B::clear() i nie musząc kopiować interfejsu w klasie B

0

ale skoro B dziedziczy po A, to w instance managarze znajdą się również klasy bazowe B z klasy A, więc wystarczy że podziedziczysz po A, a następnie wywołasz sobie składową wirtualną

0

dobra, sam doszedłem. zrobiłem tak:

template<class T>
class InstancesController : public T
{
	public:
		InstancesController() ;
		virtual ~InstancesController() ;

		static const unsigned getNumberOfInstances() ;
		static const unsigned getNextIndex() ;
		static InstancesController<T> *getInstance(unsigned index) ;
		static void clear() ;
	private:
		static std::map<unsigned, InstancesController<T>*> instances ;
		static unsigned nextIndex ;
		const unsigned index ;
};

klasy:

	class A_
	{
		public:
			A_(){}
			virtual ~A_(){}
	};
	typedef InstancesController<A_> A ;


	class B_ : public A
	{
		public:
			B_(){}
			virtual ~B_(){}
	};
	typedef InstancesController<B_> B ;


	class C_ : public A
	{
		public:
			C_(){}
			virtual ~C_(){}
	};
	typedef InstancesController<C_> C ;


	class D_ : public B, public C
	{
		public:
			D_(){}
			virtual ~D_(){}
	};
	typedef InstancesController<D_> D ;

każda z operacji:

		A::clear() ;
		B::clear() ;
		C::clear() ;
		D::clear() ;

działa

0

@cppppppp bo najpierw sprawdzany jest sam fakt istnienia niejednoznacznych odwołań, a dopiero potem to czy w ogóle możesz sie do nich odwołać. Tzn nie ma znaczenia czy będzie to dziedziczenie public, protected czy private - jeśli znajdzie sie niejednoznaczność to będzie błąd, nawet jeśli w danym kontekście tylko jedna opcja jest dostępna.

0
krwq napisał(a)

ale skoro B dziedziczy po A, to w instance managarze znajdą się również klasy bazowe B z klasy A, więc wystarczy że podziedziczysz po A, a następnie wywołasz sobie składową wirtualną

nie o to chodzi. InstanceManager ma zliczać kolejne instancje danych typów. jeśli utworzę 1 obiekt A, 1 B, 2 C i 1D, to
A::getNumberOfInstances() == 6
B::getNumberOfInstances() == 2
C::getNumberOfInstances() == 3
D::getNumberOfInstances() == 1

jeśli bym dziedziczył wirtualnie, to oczywiście te wyniki będą inne, zaraz napiszę do tego testy

0

krwq, shalom, dzięki za odpowiedzi, na razie działa ;)

0

jak ci się nie chce tak długo pisać to już lepiej zrobić:
#define IC(a) InstancesController<a>

0
krwq napisał(a)

jak ci się nie chce tak długo pisać to już lepiej zrobić:
#define IC(a) InstancesController<a>

od jakiegoś czasu jestem uczniem nowej szkołu, #define to zło i szatan :)

0

Taaaa...to spróbuj napisać funkcję,która jako parametry domyślne,nie podawane przez programistę przyjmuje numer linii w której została wywołana oraz nazwę pliku z miejsca wywołania ;]

no bez przesady... includów i informacji debugowych nie zrobi się inaczej niż preprocesorem, ale tam gdzie można, należy go unikać

0

ja tam sobie używam jako skróty.

często w różnych problemach algorytmicznych jako skrótowce używa się różnych definicji:

#define ALL(x) x.begin(),x.end()
#define REP(i,n) for (int i=0; i<(n); ++i)
#define FOR(var,pocz,koniec) for (int var=(pocz); var<=(koniec); ++var)
#define FORD(var,pocz,koniec) for (int var=(pocz); var>=(koniec); --var)
#define FOREACH(it, X) for(__typeof((X).begin()) it = (X).begin(); it != (X).end(); ++it)
#define PB push_back
#define PF push_front
#define MP(a,b) make_pair(a,b)
#define SIZE(x) (int)x.size()

1 użytkowników online, w tym zalogowanych: 0, gości: 1