engine design decisions/opinions/questions

Started by
7 comments, last by fireking 20 years, 4 months ago
im just now getting to the point where its important for me to actually utilize several features of oop. I''m programming a 3d engine for a game ive been working on for a very long time (mostly design). I have a few questions, and if you dont see something i mention, and you have a tip, point it out. 1. When creating a base class, in which you know will be inherited at some point, should you put virtual functions in public access or protected access? 2. Can classes that have inherited functions from another class access that class''s private functions? I dont think they can, but i wanted to double check. 3. What exactley is friend for? I know the definition of friend in oop, but could someone show a useful example of where it would be impossible to accomplish something without the friend feature? 4. Your opinion on singleton''s in huge projects, good idea/bad idea? 5. The node hierarchy concept for managing objects within the world, linked list good enough? 6. Feed concept? What i mean by feed is, you feed your main engine class everything that needs to happen, and by using a fast sort technique, the engine will sort everything by texture and other expensive operations, in order to accomplish the assembly of the scene the fatest. Good idea? Before you suggest it, I''ve taken a look at enginuity (and im still reading it).
--FirekingOwner/LeaderFiregames Development &Blackdragon Studios
Advertisement
1) protected stuff would be for internal class management. public would be classes that interface with everything else but the object itself, usually. The public stuff should be the major interface to the class, the protected stuff would be just to make the coding more readable, like divide and conquer. That''s my opinion.

2) no.
3) friend allows another class to have public privileges on either everything or single functions. This is usually bad design, but sometimes, it can''t be avoided as you say (well it can, but it''s nice to have it).

like

class CVector{public:    friend ostream& operator << (ostream& o, const CVector& C) const    {          o<<this->x<<", "<<this->y<<endl;          return o;    }    friend CVector& operator * (float k, const CVector& C)    {        CVector Temp = C;        Temp.x *= k;        Temp.y *= k;        return Temp;    }};


allows you to do

cout<<"Vector : "<
CVector D = 0.5f * C;

4) I don''t see any major particular problem with them, as long as they are use sparingly and wisely (initialisation order). Anyhow, they are no different than having, say a CWorld class that contains absolutely everything in the world, and has a CRenderer object, a CPhysics Object, .... which are basically singletons. If you are absolutely sure you won''t require any other instances of the class, why not.

5) not sure about what you are talking about
6) It''s a balance between overhead and flexibility. The overhead shoudl be quite low, if it is well designed and not down to too much detail. Like bundle your particles in one particle systembefore feeding a bunch of them to the renderer.

Everything is better with Metal.

quote:Original post by fireking
im just now getting to the point where its important for me to actually utilize several features of oop. I''m programming a 3d engine for a game ive been working on for a very long time (mostly design). I have a few questions, and if you dont see something i mention, and you have a tip, point it out.
Well, I''m still learning alot as well, but here are my 2 cents:
quote:
1. When creating a base class, in which you know will be inherited at some point, should you put virtual functions in public access or protected access?
2. Can classes that have inherited functions from another class access that class''s private functions? I dont think they can, but i wanted to double check.
Protected access is specifically for allowing access to a classes members from derived classes while keeping them private to all other classes. So, no, you can not access private members in a base class from a derived class, that is what protected is for.
quote:
3. What exactly is friend for? I know the definition of friend in oop, but could someone show a useful example of where it would be impossible to accomplish something without the friend feature?
Friend is for negating everything I just said. It allows access to a classes private/protected members from a class that is declared a friend. Strict OO designers often frown upon the usage of friend as it violates encapsulation, but, you know, whatever. A good example (I think): say you want a texture manager to be responsible for creating textures and handing out handles (or smart pointers) to them but you don''t want any class other than the texture manager to be able to directly create textures. Make the constructor for the texture class private and then declare the texture manager class as a friend to the texture class.
quote:
4. Your opinion on singleton''s in huge projects, good idea/bad idea?
Search the forums. This is a debate/argument/flame ware that gets had here about once a month (or more). My opinion is that the opinions regarding this question are so varied that it boils down to a style issue.
quote:
5. The node hierarchy concept for managing objects within the world, linked list good enough?
Don''t know for sure, but I have heard it said that there are better data structures for representing tree structures than a linked list...
quote:
6. Feed concept? What i mean by feed is, you feed your main engine class everything that needs to happen, and by using a fast sort technique, the engine will sort everything by texture and other expensive operations, in order to accomplish the assembly of the scene the fatest. Good idea?
Here''s the basic progression:
1. Update all objects in your scene graph (ai, movement, physics, etc...).
2. Take all objects in a set and perform any visibility culling that you are doing.
3. Sort that set as you have mentioned.
4. Render the set you have left.
Of course, that''s a quick and dirty simplification of the process (especially 1.).



peace and (trance) out

Mage
---------------------------------------------------There are 10 kinds of people in the world:Those that understand binary, and those that dont...Mage
About the friend keyword. Designers of C++ thought it might come in handy so they provided it. It is a controlled way to grant access under circumstances for efficiency purposes. Keyword here is: controlled or documented access. The objects participating in friendship relation should be conceptually close like a task object doing something on another object or an outer class grants friendship to inner class.
protected is useful for implementing the Template Method Design Pattern (which I find myself using a lot). It indicates to people that overriding the method will mean the new method is called in some controlled way as part of some sequence. For example, you might have some algorithm which allows derived classes to provide their particular way of doing things but it will still be called in a particular order. eg

void Print() {
DoImediatelyBeforePrint();
DoPrint();
DoImediatelyAfterPrint();
}

Print is non-virtual public.
Do... are all protected virtual.

Hope that makes sense

Pete

PS www.gotw.ca has lots of useful articles. Normally I''d pull up a load of links for you but I think you''d enjoy searching through it yourself.
quote:Original post by petewood
protected is useful for implementing the Template Method Design Pattern (which I find myself using a lot). It indicates to people that overriding the method will mean the new method is called in some controlled way as part of some sequence. For example, you might have some algorithm which allows derived classes to provide their particular way of doing things but it will still be called in a particular order. eg

void Print() {
DoImediatelyBeforePrint();
DoPrint();
DoImediatelyAfterPrint();
}

Print is non-virtual public.
Do... are all protected virtual.

Hope that makes sense

Pete

PS www.gotw.ca has lots of useful articles. Normally I''d pull up a load of links for you but I think you''d enjoy searching through it yourself.



there''s a problem with that though, considering the following

class bag
{
public:
int item_count;
int stores_visited;
virtual void GoShopping();
};
class big_bag : public bag
{
public:
virtual void GoShopping();
};

lets say that class bag''s GoShopping() function sets stores_visited to 1, and item_count to 10

now lets say we create a new big_bag within our code some where, and call GoShopping. Nothing will happen, because its been overridden from the inherited class, and we didnt define GoShopping in the newer class.

You might say to your self, well maybe we should define it. But if you want things to happen in a time line, you can''t use this method. What im saying is, what if in the new goshopping function, you wanted to add only a store. You could do that, but only if you do what the first goshopping function was supposed to do. Meaning that, every class that keeps inheriting each new class, will have to redefine what the function did in each class.

class a;
class b : public a;
class c : public b;

in order for class c to call a function that each c,b,and a all have, it has to redefine it, entirely. The only other way is to force it

c::b::a::create();
c::b::create();
c::create();

which is, in my opinion, bad design.
--FirekingOwner/LeaderFiregames Development &Blackdragon Studios
quote:
A good example (I think): say you want a texture manager to be responsible for creating textures and handing out handles (or smart pointers) to them but you don''t want any class other than the texture manager to be able to directly create textures. Make the constructor for the texture class private and then declare the texture manager class as a friend to the texture class.

There''s a much easier and more explicit way to do that if you make the texture class privately nested inside the texture manager. Oliii provided some good examples on the use of friend. I am very anti-singelton, because it tends to be abused as a substitute for global variables. Try and avoid them as much as possible, because, if not used properly, they can destroy any hope of using that piece of code in another project.
the main point of a singleton is to ensure only one version of the class exists in memory during run time. No big deal, i can think of several ways to do that without a singleton. Although i do like the idea of making it impossible to create another copy.
--FirekingOwner/LeaderFiregames Development &Blackdragon Studios
quote:Original post by fireking
there''s a problem with that though, considering the following

class bag
{
public:
int item_count;
int stores_visited;
virtual void GoShopping();
};
class big_bag : public bag
{
public:
virtual void GoShopping();
};


It is normal practice to call the base class function before doing the new stuff (or after it depending on what is appropriate). This can be documented.

This topic is closed to new replies.

Advertisement