Jump to content
  • Advertisement
Sign in to follow this  
bilsa

static variables for an Object instance?

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey! I got a little problem. I have a functions like this:
class MyObject {
public:
	template <class T>
	void Func() {
		//only initialize once
		static unsigned int = /*some value*/;
	};
};

The thing is that I want the nSomeValue to be consistent for only ONE instance of MyObject. Then when I create a new MyObject, I want Func() redo the initialization for the nSomeValue: //Here I want to initialize nSomeValue for //only obj1, so when I call Func() again on //this object, I get the already calculated //value. MyObject obj1; obj1.Func<Type_1>(); //Here I want obj2.Func() make its own //initialization of nSomeValue //BUT I do NOT want it to change the //value in obj1.Func() ! MyObject obj2; obj2.Func<Type_1>(); So basically I want Func() to have a static variable, BUT I want it to be static only with ONE instance of the OBJECT - NOT across ALL the objects of type MyObject. Would appreciate any help on this :) bye!

Share this post


Link to post
Share on other sites
Advertisement
then all you want is a standard private instance variable ... just never change it except in the constructor ...

the whole point of private and protected variables is not to protect a class from having to "do the right thing" with it's own variables (it is assumed that the writter of the class will not do something that violates his own intentions, while writing the class) ... it is to prevent code written in OTHER places, or other classes from doing bad stuff with this class ...

so in your class, if you use a private member variable - then no one but member functions can change it ... and if you only change it in the constructor, as intended, all is well.

Share this post


Link to post
Share on other sites
Yeh, but actually... the problem is not that simple:

It is not a normal function, its a template function :)


class MyObject {
public:
template <class T>
void Func() {
//only initialize once
static unsigned int = /*some value*/;
};
};




Sorry, I was trying to simplify the problem :)
You see, Now I can't save the variable as a member, since there is a new variable for each Func<T>() instance :(

Share this post


Link to post
Share on other sites
Is there any way you could get away with templating the *class* instead of the function? Otherwise, I'd have to see more of what you're really trying to do (and the justification for doing it) to be of any help...

Share this post


Link to post
Share on other sites
If this is posible, it really should not be, because it causes one unfixable linker problem:

templates are only instantiated if used ...

C++ types are static, and their shape must be 100% exactly the same in all compilation units ...

So 2 instances of the same class cannot have different layouts ... but you are trying to do just that.

// in compilation unit 1
MyClass<int> a;
a.Func(43);
a.Func(43.0);
// MyClass now has instantiated an int and float/double version of Func

// in compilation unit 2
MyClass<int> b;
b.Func('b');
// MyClass now has a char version of Func.

so IF the compiler did what you want, then the shape of a is something with 2 variables in it, and the shape of b is something with 1 variable in it ... hence they are not the same type, and are completely incompatible ...

but the short answer is, even without these weird situations, there is just no langauge mechanism to express the concept you are talking about (statically). The langauge ONLY supports static / global variables - which exist shared by either the compilation unit (static non-members), the whole program (globals, static class members), all programs which use the library (certain kinds of DLL variables). Or Local / Instance variables (which is the closest thing to what you want).

If you don't mind using a dynamic system, you can do crazy stuff with a list of instance variables ... IF they have a common type base ... but that'll take a little more thinking through ...

BTW - what do you actually want to acomplish?

Share this post


Link to post
Share on other sites
yes i agree with Zahlman, what you need will require some serious justification.

if not, i guess you could try this, a bit of a hack though.


class MyObject {
public:
template <class T>
void Func() {
static unsigned int vars[100] = /*some value*/;
int varUsedInCalcs = 0;
if( typeid(T) == typeid(int) )
varUsedInCalcs = vars[0];
else
if( typeid(T) == typeid(float) )
varUsedInCalcs = vars[1];

// etc etc.

};
};



That is _REALLY_ Ugly and i probably shouldn't be encouraging you
but your situation is wierd.

Share this post


Link to post
Share on other sites
Hehe, maybe this aint a newbe question after all...

The thing is that I have made a Visitor pattern that does NOT
use any RTTI beyond the rtti that is stored IN the VISITOR class

So basically...

Im using something like this, which works for ONLY one
visitor... :



class RenderableVisitor : public Visitor, public VisitorCallback {
unsigned int m_nCount;
public:
RenderableVisitor() : m_nCount(0) {
callbacks.RegisterCallback<Renderable>(this);
}

virtual void Visit(Base* pBase) {
//Since the object has come here IT MUST have been of Renderable type...
//otherwise it would never have come here...
Renderable* pRenderable = reinterpret_cast<Renderable*>(pBase);
}
};







Now I can use this like this:

Visitor* pVisitor = new RenderableVisitor();
Base* pBase = new Renderable();

pBase->Accept(pVisitor);

And by sending the real type of pBase to pVisitor's template
function:


class Visitor {
protected:
VisitorCallbackMap callbacks;
public:
Visitor() {
}

template <class T>
bool Visit(T* pObject) {
//The real object type is deduced and sent to a callbackmap
//which passes pObject to the Registered Callback function
//from RenderableVisitor
bool bReturn = callbacks.Execute(pObject);
return bReturn;
}
};







Now after sending the pObject to callbacks.Execute() this happens:


class VisitorCallbackMap {
template <class T>
inline
bool Execute(T* pObject) {
//Get the Registered Callback function from RenderableVisitor
//and pass the pObject to it

//The trick is the type_ids.GetID<T>() which contains the
//static int for each Registered callback...

if(VisitorCallback* pCallback = list[type_ids.GetID<T>()]) {
pCallback->Visit(pObject);
return true;
} else {
return false;
}
}
};







The trick is the type_ids.GetID<T>() which is the Func<T>() function.
This function keeps track of the RegisterCallback<U>() function, which calls type_ids.GetID<U>() and inserts the
callback with the ID returned from type_ids.GetID<U>().

Now a Renderable object type will call type_ids.GetID<SomeObject>() and thus will get the
same ID that RegisterCallback<SomeObject>() got.
Then I can use this to get the Callback function from a
container by indexing...

This way I got a perfectly working RTTI for Visitors.

So this gives me:

1. Adding operations is simple by making a new derived Visitor object.
2. Usually this come at the cost of having to add a Visit(T) function for each type T you want a Visitor to support. AND ALL
visitors NEEEED ALL the types... which is a burning hell when
updating the engine :(!
BUT this design lets me use the Visitor pattern like with a
dynamic_cast except its Tens of times faster and actually
only 3 times slower than using a custom built RTTI system
with enums.

So basically I can eat the cake and still have it :)

That is if someone helps me solving this problem with the static
shit variable since After initializing a derived Visitor like
the RenderableVisitor, the type_ids.GetID<T>() function which
stores the indexes to the callback map for each registered type
will be messed up and will NOT work for a new derived Visitor.

Otherwise this would actually be areal breaktrhough in the
Visitor pattern, actually It already is. But you can only traverse
A container ONCE with a SINGLE visitor, and if you want to
traverse the Container with another Visitor... you will first
need to destroy the old one and REINIT in the type_ids<T>.GetID() aka MyObject::Func<T>()...
Which is only halfway of what I want to have :(


SORRY about the underlined text, I got no clue why it does like that.

c ya guys!
Fruny - underlined text fixed, <U> is HTML for underline.

[Edited by - Fruny on October 7, 2004 5:30:07 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!