Błąd przy użyciu wskaźnika do funkcji wirtualnej

0

Witam.
Stworzyłem klasę mającą działać jak właściwości w C# itp:

KLASA WŁAŚCIWOŚCI

 
template<typename P_TYPE>
class vClassProperty
{
public:
	typedef P_TYPE(__thiscall * GetterType)();
	typedef void  (__thiscall * SetterType)(const P_TYPE&);
private:
	GetterType __getter;
	SetterType __setter;
public:
	vClassProperty(GetterType getter, SetterType setter) :
		__getter(getter),
		__setter(setter)
	{
	}
	vClassProperty & operator=(const P_TYPE & val)
	{
		__setter(val);
		return *this;
	}
	operator P_TYPE()
	{
		return __getter();
	}
};

Chciałem użyć jej potem w innej klasie:

class IWindow : public IGeneric
{
protected:
	vEvent *m_event = nullptr;
// Getters and setters:
	virtual void __setFullscreen(const bool &_value) = 0;
	virtual bool __isFullscreen(void) = 0;

	virtual void __setWidth(const int& value) = 0;
	virtual int  __getWidth(void) = 0;

	virtual void __setHeight(const int& value) = 0;
	virtual int  __getHeight(void) = 0;
	//--------------------------------------------------
public:
	typedef IGeneric Super;

	__forceinline void AttachEvent(vEvent *_ev)
	{
		m_event = _ev;
	}
	virtual void Create(const char* title, int width, int height) = 0;
	virtual void CreateContext() = 0;
	virtual void Destroy() = 0;
	virtual void PollEvent() = 0;
	virtual void Swap() = 0;

	vClassProperty<bool> Fullscreen;
	vClassProperty<int> Width, Height;

	IWindow() :
	  Fullscreen(__isFullscreen, __setFullscreen),
	  Width(__getWidth, __setWidth),
	  Height(__getHeight, __setHeight)
	{

	}
};

 

Ale w trakcie kompilacji mam następujące błędy:

no matching function for call to 'vClassProperty<bool>::vClassProperty(<unresolved overloaded function type>, <unresolved overloaded function type>)'
no matching function for call to 'vClassProperty<int>::vClassProperty(<unresolved overloaded function type>, <unresolved overloaded function type>)'

Ma ktoś pomysł, jak to naprawić?

Korzystam z najnowszego TDM-GCC-64.
Projekt przenoszę z Visual Studio 2013, gdzie używałem to tego celu __declspec(property).

1
    typedef P_TYPE(__thiscall * GetterType)();
    typedef void  (__thiscall * SetterType)(const P_TYPE&);

To są wskaźniki na funkcje. Nie wskaźniki na funkcje będące członkami klasy. Ponadto z jakiegoś powodu wymuszasz konwencję wywołania thiscall.
Próbujesz przypisać funkcje - członków klasy (wskaźnik na funkcję-członka klasy i na zwykłą funkcję to zupełnie różne rzeczy, najczęściej o różnych wielkościach, więc nawet żadne rzutowanie tu nic nie da, szczególnie, że później tą funkcję musisz wywołać na jakimś konkretnym obiekcie)

      Fullscreen(__isFullscreen, __setFullscreen),
      Width(__getWidth, __setWidth),
      Height(__getHeight, __setHeight)

Jeśli chcesz "szybki fix" to użyj std::function, przy czym to ma swój koszt wydajnościowy (zalecam lekturę o wadach tego szablonu:

    typedef std::function<P_TYPE()> GetterType;
    typedef std::function<void(const P_TYPE&)> SetterType;

i potem wywołuj za pomocą std::bind bądź lambdy:

      Fullscreen(std::bind(&__getFullScreen, this), std::bind(&__setFullScreen, this, placeholders::_1)),
      Width([this](){ return __getWidth; }, [this](int v) { __setWidth(v); })

Przy okazji: nie masz prawa używać __ (podłoga podłoga) w nazwach swoich identyfikatorów. Nie tylko wygląda to tragicznie, ale też jest zakazane przez standard.

1

Można też tak:

template<typename TClass, typename TProp>
class Property{
	typedef TClass* PTClass;
	typedef TProp(__thiscall TClass::*Getter)();
	typedef void(__thiscall TClass::*Setter)(const TProp&);

public:
	Property(PTClass object, Getter getter, Setter setter) :
		_object(object), _getter(getter), _setter(setter){}
	operator TProp(){
		return (*_object.*_getter)();
	}
	Property& operator=(const TProp& val){
		(*_object.*_setter)(val);
		return *this;
	}

private:
	PTClass _object;
	Getter _getter;
	Setter _setter;
};

class Jakasklasa{
public:
	Jakasklasa() :
		number(this, &Jakasklasa::_getNumber, &Jakasklasa::_setNumber){}
	Property<Jakasklasa, int> number;

private:
	virtual int _getNumber(){ 
		return _n; 
	}
	virtual void _setNumber(const int& n){ 
		_n = n; }
	int _n;
};
0

Dzięki za odpowiedzi, będę pisać cały projekt od nowa i wypróbuję te sposoby :)

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