Jump to content
  • Advertisement
Sign in to follow this  
Jiia

Namespaces in classes

This topic is 4958 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

Quote:
Original post by ajones
Sorry if I'm being dumb (I don't use inner structs very often), but can't you use inner structs instead of namespaces to do what you want?


/*
* I believe he wants to do something like this:
*/

class foo {
int member_variable;
namespace bar {
void function() {
member_variable = 3;
}
}
};
/*
* You cannot directly emulate this in C++:
*/

class foo {
int member_variable;
class bar {
void function() {
/*
* error: foo::bar is instantiatable completely independantly from a
* foo object - which foo's member_variable do we use?
*/

member_variable = 3;
}
};
};
/*
* You can work around this by mantaining a reference manually... something
* similar to this is an option:
*/

class foo {
int member_variable;
class bar_impl {
foo & parent;
bar_impl ( foo & parent ) : parent( parent ) {}
void function() {
parent.member_variable = 3;
}
} bar;
foo () : bar( *this ) {}
};

/* There is some added overhead (one reference per type/subgroup) using this
* method. Considering the only good argument for class sub-namespaces seems to
* be related to intellesense, I might recommend using non-member functions in
* conjunction:
*/


class pie {
public:
void foo_eat( void ) {}
void foo_make( int arg ) {}
void foo_throw_it( void ) {}
void bar_eat( void ) {}
void bar_make( int arg ) {}
void bar_throw_it( void ) {}
};

namespace foo {
void eat( pie & self ) { self.foo_eat(); }
void make( pie & self , int arg ) { self.foo_make( arg ); }
void throw_it( pie & self ) { self.foo_throw_it(); }
}

namespace bar {
void eat( pie & self ) { self.bar_eat(); }
void make( pie & self , int arg ) { self.bar_make( arg ); }
void throw_it( pie & self ) { self.bar_throw_it(); }
}

pie my_pie;

//equivilant lines:
my_pie.foo_eat();
foo::eat(my_pie);

//equivilant lines:
my_pie.bar_make(3);
bar::make(my_pie,3);

...


Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by MaulingMonkey
I believe he wants to do something like this:

/* assignment to outer class member variable from inside inner class*/

You cannot directly emulate this in C++


If so, there's a directly related discussion in the C++ Users Journal (you can also find the article here) that provides examples of how to work around the problem (although they're ugly); it also references a standard revision that should solve this language defect (access rules for nested classes).

Note that this is only relevant if Jiia does intend to mutate an outer member variable from an inner class; as long as Jiia only requires access from outer to inner scope (i.e. MadMan uses Particle:: members, but Particle:: doesn't make use of ParticlePhysics:: members), then an inner class is fine.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
Original post by ajones
Sorry if I'm being dumb (I don't use inner structs very often), but can't you use inner structs instead of namespaces to do what you want?


*** Source Snippet Removed ***



Actually when this thread was started I checking by doing something like that. About the closest I came to was creating an inner class that contained a reference to the outer class and overloaded the -> operator in the inner class to return a pointer to the outer class.
class Outer {

void DoSomething();

class Inner {
public:
Outer &outer;
Outer *operator->() {
return &outer;
}
};
public:
Inner Particle;
};

Outer outer;
outer.Particle->DoSomething();


In the end it's ugly and pointless.

Share this post


Link to post
Share on other sites
Am I the only one that thinks if an inner class needs knowledge of the containing class, it shouldn't be an inner class at all?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Helter Skelter
In the end it's ugly and pointless.


From my current (PhD) project's resource system (apologies for the huge source snippet - I just want to present a complete example):


class CfgElement
{
public:
explicit CfgElement(ASSET_SYSTEM::AssetDataIterator& in,
RESOURCE_SYSTEM::qualified_elements& qualifiedElements,
RESOURCE_SYSTEM::qualified_attributes& qualifiedAttributes,
const std::string& parentQualifiedName);

inline const std::string getName() const
{ return m_name;
}
inline const std::string getQualifiedName() const
{ return m_qualifiedName;
}
public:

struct elements_collection
{
public:
typedef CFG_ELEMENTS::named_elements named_elements;
typedef CFG_ELEMENTS::named_iterator named_iterator;
typedef CFG_ELEMENTS::named_range named_range;

typedef CFG_ELEMENTS::ordered_elements ordered_elements;
typedef CFG_ELEMENTS::ordered_iterator ordered_iterator;
typedef CFG_ELEMENTS::ordered_range ordered_range;
public:
const named_range get(const std::string& name) const;
const named_iterator begin_named() const;
const named_iterator end_named() const;

const ordered_iterator get(const size_t& index) const;
const ordered_iterator begin_ordered() const;
const ordered_iterator end_ordered() const;
private:
friend class CfgElement;
elements_collection();
named_elements m_named;
ordered_elements m_ordered;
}elements;

struct attributes_collection
{
public:
typedef CFG_ATTRIBUTES::named_attributes named_attributes;
typedef CFG_ATTRIBUTES::named_iterator named_iterator;
typedef CFG_ATTRIBUTES::named_range named_range;

typedef CFG_ATTRIBUTES::ordered_attributes ordered_attributes;
typedef CFG_ATTRIBUTES::ordered_iterator ordered_iterator;
typedef CFG_ATTRIBUTES::ordered_range ordered_range;
public:
const named_iterator get(const std::string& name) const;
const named_iterator begin_named() const;
const named_iterator end_named() const;

const ordered_iterator get(const size_t& index) const;
const ordered_iterator begin_ordered() const;
const ordered_iterator end_ordered() const;
private:
friend class CfgElement;
attributes_collection();
named_attributes m_named;
ordered_attributes m_ordered;
}attributes;

private:
std::string m_name;
std::string m_qualifiedName;
};



I still maintain that inner structs are a valid solution to the OP's problem - the above code compiles fine under VC++ .NET 2003, where the body of CfgElement's constructor is actually responsible for inserting both elements and attributes into the respective collections' containers. Neither element_collection not attribute_collection make any use of the outer (CfgElement) class. CfgElement's interface, given its context and suitable documentation, is clean and easily understood, despite the use of two nested structs to group semantics.

I'm sorry if I'm being a bit anal about this [razz] - I just see it as a potential solution to the OP's problem; the use of inner structs can be ugly if you need inner -> outer access (I'm certainly not arguing that point), but the OP has yet to confirm this.

Share this post


Link to post
Share on other sites
The above AP was me - took me a while to re-read and format it, and to make sure I don't sound like a complete git! [smile]

Share this post


Link to post
Share on other sites
Hi,

you have a class that does a lot of thinks, right?
And you subclassed from alot of different classes, right?
Why use inheritans at all?


/** an interface **/
class IPartical
{
public:
virtual void start()=0;
virtual void stop()=0;
};

/** an interface **/
class IAnimation
{
public:
virtual void setAnim(/*...*/)=0;
};

class Partical : public IPartical
{
public:
void update();
void start( /*...*/ );
void stop( /*...*/ );
// ...
};

class Animation : public IAnimation
{
public:
void update();
void setAnim( /*...*/ );
//...
};

class MadMan
{
public:
void update()
{
_partical-update();
_animation-update();
}

void setAnim( /*...*/ );

private:
Partical* _partical;
Animation* _animation;
};

or

class MadMan : public IPartical, IAnimation
{
public:
void update()
{
_partical-update();
_animation-update();
}

void start( /*...*/ );
void stop( /*...*/ );
void setAnim( /*...*/ );


private:
Partical* _partical;
Animation* _animation;
};


Share this post


Link to post
Share on other sites
Quote:
Original post by ajones
Quote:
Original post by MaulingMonkey
I believe he wants to do something like this:

/* assignment to outer class member variable from inside inner class*/

You cannot directly emulate this in C++


If so, there's a directly related discussion in the C++ Users Journal (you can also find the article here) that provides examples of how to work around the problem (although they're ugly);


I meant with that particular syntax, you'll note my example later on with references (which are more directly analagous at the expense of some overhead). IIRC, Java's nested classes do in fact work as shown in example 2, but that by necessity limits nested classes to being tied to an implementation.

Quote:
it also references a standard revision that should solve this language defect (access rules for nested classes).


In the meantime this can be fixed with a simple friend statement or two.

Quote:
Note that this is only relevant if Jiia does intend to mutate an outer member variable from an inner class;


Which I suspect, considering the discussions of his class and the possibility of breaking it up are refuted on the basis of too much shared information for not enough precieved payback.

That said, this is a valid point.

Share this post


Link to post
Share on other sites
Quote:
Original post by Helter Skelter
Regardless, programming languages have nothing to do with bad design.

You're telling me that classes should never have a lot of functions that do several different things. Why not? If a character can kick, throw knives, and jump, then I need three classes? You're reasoning is not realistic. Perhaps with your file parser, but not with my project. There's no way I can divide to the level you're suggesting.

Quote:
Quote:
If there were a way to group functions by purpose, it would be much more manageable. Or at least I would think so.

Ummmm...that's what classes are for.

Then what represents a single entity? I just want a money wrapper. You're telling me to give 20s to one guy, 50s to another, and 100s to someone else. It doesn't make sense. It's all my money, I just want to organize it. I just don't have enough pockets.

Quote:
that depends. If the string functions can be considered general purpose they will most likely end up in a utility class, string class, or in their own little section of the program. Support for strings is broad enough that they in all likelyhook belong elsewhere.

I'm trying to tell you that the functions are directly linked to the class. They are class functions. You're telling me that a class can have functions that only do one thing? A file class can open and close, but never read or write? Those are two different groups of functions, and both belong in the file class. I've seen the same pattern in standard code, in Microsoft code, and in libraries. One class has many functions, yet you could almost always split those functions into four or five groups.

The nested cass idea is a nice suggestion, but it's not really what I want. Perhaps if it could be wrapped up into a very simple management process. But it can't. The inside class methods need lots of help to interact with.. itself, in this case, on the outside.

[Edited by - Jiia on July 22, 2005 2:37:49 AM]

Share this post


Link to post
Share on other sites
Prehaps a virtual multi-diamond of doom?


class foo_funcs_1;
class foo_funcs_2;
class foo_funcs_3;

class foo_base {
protected:
... classwide members ...
public:
virtual foo_funcs_1 & funcs_1() = 0;
virtual foo_funcs_2 & funcs_2() = 0;
virtual foo_funcs_3 & funcs_3() = 0;
virtual const foo_funcs_1 & funcs_1() const = 0;
virtual const foo_funcs_2 & funcs_2() const = 0;
virtual const foo_funcs_3 & funcs_3() const = 0;
};

class foo_funcs_1 : public virtual foo_base {
protected:
... specific function group related only ...
public:
void func1() { ... }
void func2() { ... }
void func3() { ... }
};

class foo_funcs_2 : public virtual foo_base {
protected:
... specific function group related only ...
public:
void func4() { ... }
void func5() { ... }
void func6() { ... }
};

class foo_funcs_3 : public virtual foo_base {
protected:
... specific function group related only ...
public:
void func7() { ... }
void func8() { ... }
void func9() { ... }
};

class foo : public foo_funcs_1 , foo_funcs_2 , foo_funcs_3 {
public:
foo_funcs_1 & funcs_1() { return *this; }
foo_funcs_2 & funcs_2() { return *this; }
foo_funcs_3 & funcs_3() { return *this; }
const foo_funcs_1 & funcs_1() const { return *this; }
const foo_funcs_2 & funcs_2() const { return *this; }
const foo_funcs_3 & funcs_3() const { return *this; }
};






Things get downright evil if funcs_1/funcs_2 need to access each other however (circularly anyways - single-way could be handled by another virtual inherit)

EDIT: Circular dependancy solvable by virtual base class. Source updated to provide example. You'll take about the same preformance hit AFAIK (maybe less with optimization) as the inner classes method due to the mechanics of virtual inheritence, but it's much less of a hassle to use/develop.

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!