Namespaces in classes

Started by
35 comments, last by Holy Fuzz 18 years, 9 months ago
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);...
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.
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.
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?
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.
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]
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;};orclass MadMan : public IPartical, IAnimation{public:   void update()   {      _partical-update();      _animation-update();   }   void start( /*...*/ );   void stop( /*...*/ );   void setAnim( /*...*/ );private:   Partical* _partical;   Animation* _animation;};
“Always programm as if the person who will be maintaining your program is a violent psychopath that knows where you live”
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.
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]
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.

This topic is closed to new replies.

Advertisement