C++ Design Question

Started by
6 comments, last by kressilac 24 years, 4 months ago
You'll have 15,000 copies of the members of the class, but only one copy of the code. The compiler is smart enough to know to only make one copy, regardless of inlining.

If you want a member (variable) of a class to be shared between ALL instances of that class, prefix it with the "static" keyword, i.e.

class A {
pubilc:
int m_a;
static int m_b;
};

if you create 15,000 A classes, you'll have 15,000 m_a's, but only one m_b.

Note that you have to explicitly define static variables in your source as if they were globals - "int A::m_b = 0;", or you'll get link errors.

Probably more than you ever wanted to know.

Mason McCuskey
Spin Studios
www.spin-studios.com

Founder, Cuttlefish Industries
The Cuttlefish Engine lets anyone develop great games for iPad, iPhone, Android, WP7, the web, and more!
Advertisement
Probably the fastest response that I have ever received. Thanks you cleared up a pile of questions I had.

Kressilac

------------------
Derek Licciardi

Derek Licciardi (Kressilac)Elysian Productions Inc.
Also, IMO, don't waste your time with get/set functions for every variable. You only really want to use them if something unintuitive happens when you get/set variables. (i.e. when you change a database field it needs to validate the data, set a recordChanged flag etc.)

A better way to encapulate that kind of thing is just to typedef something like ATTRIBUTE as an int.

-the logistical one-http://members.bellatlantic.net/~olsongt
Note that an inlined function is not a function at all. It works similarly to how a #define macro works, except the compiler does type-checking and you're allowed a function syntax.

In other words, an inlined function isn't a function, it's a macro. The code to execute the function is inserted everywhere in your source code where the inline function is called.

So, here's a longer answer to the question, "what's created when I instantiate N copies of a class?":
- N instances of each member variable
- 1 instance of each member function
- M copies of the code in your inline function, where M is the number of times that function call appears in the source code.

HTH.

Stoffel: The compiler is supposed to be able to pick and choose which functions it will treat as inline (meaning the actual code is placed wherever you called the function). You just specify which functions you would like to be inline.

Kind of like the old register variable type...

- null_pointer

<<
Also, IMO, don't waste your time with get/set functions for every variable.
>>

You should never directly access member variables in a class unless you are absolutely sure that the way that variable is used will never change, which in most cases, you aren't.

If you access a particular member variable of a class directly throughout a program, and then you decide that you need to do something when that variable is accessed (such as keeping a reference count or something), you will have to change each and every place in your program where you access that variable. However, if you use an access routine, then you just add the additional code to the class function.

If you're worried about speed, then make the access routine inline. Then it is essentially identical to directly accessing the variable itself, but allows for unforseen future changes.

Josh

I have the following Classes:

CPChar and CPCharAbilities. CPChar is the container class for all of my character code. Inherited from this will be my NPC class and my PC class in an online roleplaying game.

Class CPChar {
private:
CPCharAbilities *abilities;
public:
...
}

Class CPCharAbilities {
private:
int str;
int dex;
int ...
public:
void RerollStats();
inline int GetSTR() {return (str);}
...
}

Two questions from this and pardon the syntax if it is not correct as I did this from my head. If I instantiate a PChar say 15000 times representing the number of individual monsters and player characters in the game at one time, will the RerollStats function get instantiated 15,000 times as well or will the compiler optimize this by sharing the code in the executable? Also what is the effect of the inline function with respect to the same question. My initial research tells me that the former is instantiated each time and the latter is not as it acts like a #define macro would in C.

If what I am thinking is true is there a way around this while still enjoying the benefits of encapsulation or am I being forced through some C++ scalability limit to revert back to a procedural way of thinking to reduce the memory footprint an object oriented way of thinking would cause. Because this is an online game performance and scalability are of utmost concern.

Thanks
Kressilac

ps I am coding on Win32 for NT 4.0 Svc pack 5. I use Visual Studio 6.0 and have the first service pack installed.

------------------
Derek Licciardi

Derek Licciardi (Kressilac)Elysian Productions Inc.
First, about stoffel's post and inline functions. An inline function is EITHER a function OR a macro OR BOTH...depending on the compiler's analysis of the situation. The COMPILER looks at HOW much memory is taken up by expanding the code (MACRO), and how much by making it a function and calling it, and it chooses the best option (ideally). It's really simple, and here's some examples of when and where it will choose each.

Ex 1 - When an inline function consists on nothing but a single function call itself, it will ALWAYS be expanded (cause the space for calling a FUNCTION version is equal to the space of EXPANDING it, and expanding it saves the overhead of having the function anywhere in the code.

Ex 2 - When a fairly small function is called only a few times (compiler dependent, but usually around 8) it is expanded.

Ex 3 - When a fairly small function is called MANY times (compiler dependant) it is made into a function and called like all other functions.

Ex 4 - When a LARGE function is called only a few times. This one is compiler dependant. Some analize the situation and choose whichever is more effiecent, some just perform the test for number of uses and if it is below the threashhold they expand it as a macro (never mind the inefficiency of this particualar case).

Hope that helps.

BTW jharler is 100% correct in his post.

about the number of things instantiated - stoffels post is correct except the inline issue (which i addressed above). But I wanted to explain WHY so you would understand it better. A FUNCTION (any function) is STATIC by default, a variable is not. This is why when you want to use a function in another module you don't have to use static on the body, or extern on the prototype, but you do for shared variables. But be VERY carefull...since static behavior is assumed for functions, they made using the static keyword on MEMBER FUNCTION do something else. A STATIC MEMBER FUNCTION is one that can be accessed without an instance of the class (it doesn't pass a 'this' pointer, and it can be called directly).
Example:
class Useless
{
public:
static GetClassName(void) {return "Useless";}
};
in main you can say:
cout << Useless::GetClassName();
and it calls that function directly. There are very few uses for such functions, but there is ONE VERY IMPORTANT ONE...for implementing FACTORIES...a very importan OO design pattern. This allows you to have a class member function that controls creation of instances of the class...pretty neat;

This topic is closed to new replies.

Advertisement