This topic is 3986 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello, After seeing it done in Boost::smart_ptr, I decided it would be helpful to overload the -> operator in a few of my classes. For example, my CEffect class is a wrapper for ID3DXEffect interface. At present, I have been having to use the effect like this:
LPD3DXEFFECT CEffect::GetEffect( void )
{
return  m_effect;
}

/////////////////////////////////////////////////

m_effect->GetEffect()->SetMatrix("World", &temp );


I hoped I could do this too:
LPD3DXEFFECT CEffect::operator->( void )
{
return  m_effect;
}

/////////////////////////////////////////////////

m_effect->SetMatrix("World", &temp );


... but it doesn't seem to work. I am sure I am doing something simple wrong. Any advice gratefully received. Simon

##### Share on other sites
Hmm, I don't know. It just doesn't seem like such a great idea. In the case of Boost's smart pointers, it's still intuitive. But in this case it would be very confusing to overload that operator.
Anyhow it seems like you need to return a pointer (or some other class overriding the -> operator), so that the -> is a valid operation on the return type.

##### Share on other sites
m_effect is a pointer, so you need to dereference the pointer to call CEffect::operator->(), which you overloaded:

(*m_effect)->...

##### Share on other sites
Hmm, no, thats not quite it.

When using the effect, Thats where it complains. Here's it written another way:

class CEffect{    CEffect( char* filename ) { m_fx = NULL ; D3DXCreateEffectFromFile( filename, m_fx, .....etc); }    ~CEffect() { SAFE_RELEASE( m_fx ); }    ID3DXEffect* m_fx;public:        ID3DXEffect* operator->() { return m_fx; }//..... other functionality}CEffect* m_effect = new CEffect("fire.fx");m_effect->SetMatrix("World", worldMatrix);///////////////////////////////////////// Outputerror C2039: 'SetMatrix' : is not a member of 'CEffect'

Does that make it any clearer?

Thanks

Simon

##### Share on other sites
Boost smart pointers are actual instances of objects, not pointers. Your m_effect variable in your last example is a raw pointer to a CEffect instance. Which means that the -> operator applies to the raw pointer.

Now if you had done this:
class CEffect{    CEffect( char* filename ) { m_fx = NULL ; D3DXCreateEffectFromFile( filename, m_fx, .....etc); }    ~CEffect() { SAFE_RELEASE( m_fx ); }    ID3DXEffect* m_fx;public:        ID3DXEffect* operator->() { return m_fx; }//..... other functionality}//An actual instance, not a pointerCEffect m_effect("fire.fx");m_effect->SetMatrix("World", worldMatrix);
then that last part should work. Do you see the difference? The operator must apply to an actual instance, not to a raw pointer to an instance.

##### Share on other sites
I just did a quick test:

class MyClass{public:	int myInt;};class TestClass{public:	TestClass(void);	~TestClass(void);	void setInt(int newInt)	{		myObject.myInt = newInt;		};	MyClass* TestClass::operator->( void )	{		return (&myObject);	};private:	MyClass myObject;};

TestClass tc;tc.setInt(20);std::cout << tc->myInt;

Compiles and prints out 20 as expected.

EDIT: Agony most likely hit the nail on it's head.

##### Share on other sites
Of course they are. I'd forgotten that.

Unfortunately, ID3DXEffect is an abstract class. It has to be a pointer :(

Guess I'll have to go back to my old way!

##### Share on other sites
Does CEffect inherit from ID3DXEffect? Or is CEffect just a wrapper around an ID3DXEffect pointer? If it is the latter, then all you need is an instance of CEffect. It doesn't matter that your wrapped effect is a pointer. -> returns a pointer anyway, so that's fine.

##### Share on other sites
Quote:
 Original post by sipicklesOf course they are. I'd forgotten that.Unfortunately, ID3DXEffect is an abstract class. It has to be a pointer :(Guess I'll have to go back to my old way!

As Agony pointed out it's the object of type CEffect which mustn't be a pointer, since if it's a pointer then the -> operator would that of a pointer and not that of an object of type CEffect. The returned value of the operator -> should be a pointer, which it is, so you don't have a problem there.

##### Share on other sites
I only skimmed the thread, so this may be completely irrelevant, but...

If the only purpose of the wrapper is to provide support for RAII, you might consider instead using boost::shared_ptr along with a custom deleter. You would then get operator->() (along with a number of other useful features and behaviors) essentially for free.

##### Share on other sites
Its the latter, a wrapper. Unfortunately, the CEffect class is used by my CResourceManager< CEffect > class, which relies on pointers and memory allocation.

Wouldn't changing this to inherit from ID3DXEffect solve this?

---

edit: jyk may have a point. The custom deleter performs the release, right?

##### Share on other sites
Quote:
 Original post by sipicklesIts the latter, a wrapper. Unfortunately, the CEffect class is used by my CResourceManager< CEffect > class, which relies on pointers and memory allocation.Wouldn't changing this to inherit from ID3DXEffect solve this?---edit: jyk may have a point. The custom deleter performs the release, right?
Here's another not-terribly-well-thought-out and perhaps-not-completely-relevant reply :)

To me it looks like you're not trying to abstract away any functionality here (that is, the fact that this is a DX-based framework is in no way kept from the user). Therefore it seems it would make more sense to simply manage objects derived from ID3DXEffect directly via smart pointers rather than using a wrapper.

In other words, I can think of two reasons you would want to wrap ID3DXEffect:

1. To support RAII
2. To abstract away its functionality

You're not doing '2', and '1' is already covered by boost::shared_ptr, so the custom wrapper seems somewhat superfluous.

I realize your resource manager class would require some reconfiguring to make it work with smart pointers, but I think this change would be worth considering.

Also, I should mention that I'm not that familiar with this part of the DX API, so I'm just assuming here that there are no technical problems with using shared_ptr in this context.

[Oop, didn't see your edit. Yes, with an appropriate custom deleter, shared_ptr will take care of freeing the resource for you (in true RAII fashion).]

##### Share on other sites
Yeah the updating of my resource manager class to use boost::smart_ptr is top of my to do list!

Thanks for the advice!

Si

##### Share on other sites
Quote:
 Original post by rip-offm_effect is a pointer, so you need to dereference the pointer to call CEffect::operator->(), which you overloaded:(*m_effect)->...

It seems that someone missed that post. So I quote it again, as it contains all the needed information to understand why the current code is not working.