C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 07-08-2009, 12:13 AM   #1
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
namespace and data hiding

Hello I have a namespace and two classes. Bar inherits Foo. How can I hide Foo from external usage? One way would be to do it like the following:

Code:
namespace Foobar {
	class Bar {
		private:
			class Foo: private Enemy {
				private:
					Suit value;
			} foos[3];
	};
}
I don't want to be able to access Foobar::Foo, But I don't think that's the ultimate way.

Any suggestions?
Tux0r is offline   Reply With Quote
Old 07-08-2009, 12:31 AM   #2
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,359
Quote:
Originally Posted by Tux0r
One way would be to do it like the following:
If you want Bar to inherit from Foo, you cannot have Foo as a nested class in Bar, methinks. A more feasible way would be to declare a namespace mamed detail in the Foobar namespace, then use the convention that this detail namespace contains implementation detail... USE AT YOUR OWN RISK.

By the way, why do you want to do this?
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-08-2009, 12:36 AM   #3
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
Thanks for your answer.

Ok the way I'm seeing it now is that I want an array of 3 Foo in Bar and to do that the right way I would have to hide Foo from rest of the program, no one else needs it!

If I nest another namespace it is still visible to the rest of the program only at another scope.
Tux0r is offline   Reply With Quote
Old 07-08-2009, 12:40 AM   #4
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,359
Quote:
Originally Posted by Tux0r
Ok the way I'm seeing it now is that I want an array of 3 Foo in Bar and to do that the right way I would have to hide Foo from rest of the program, no one else needs it!
Oh, so you just want a member array of 3 Foo objects? In that case what you have done is correct.

Quote:
Originally Posted by Tux0r
If I nest another namespace it is still visible to the rest of the program only at another scope.
Of course, hence this is a convention: a user of your library knows that whatever is in the detail namespace is implementation detail. If he/she uses the constructs found in that namespace, he/she must be prepared for his/her program to break when your library is updated, even when the update is supposed to maintain backward compatibility.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-08-2009, 12:43 AM   #5
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
Quote:
Originally Posted by laserlight View Post
Oh, so you just want a member array of 3 Foo objects? In that case what you have done is correct.
Yeah but my key point here is: is there a way to have the class Foo in the namespace without it being accessible outside of it? Because I have another base class, Enemy, and I don't see any reason to have it accessible.

It would be nice if I could use an anonymous namespace to wrap it up with but it does not have the effect I desire.
Tux0r is offline   Reply With Quote
Old 07-08-2009, 12:51 AM   #6
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,359
Quote:
Originally Posted by Tux0r
Yeah but my key point here is: is there a way to have the class Foo in the namespace without it being accessible outside of it? Because I have another base class, Enemy, and I don't see any reason to have it accessible.
Not that I know of: the detail namespace convention that I described is the way that I know to address this shortcoming. Besides, namespaces are not closed: even if such a construct existed, your users could theoretically just open your namespace and write whatever they want to easily defeat this access control without modifying any code that you wrote - you would effectively end up with another convention, albeit one that was better supported by language constructs.

Quote:
Originally Posted by Tux0r
It would be nice if I could use an anonymous namespace to wrap it up with but it does not have the effect I desire.
Not in a header file, at least.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-08-2009, 12:51 AM   #7
Registered User
 
Join Date: Apr 2006
Location: United States
Posts: 3,201
Well when you're talking about access do you mean you want to not have objects of specific classes or that they shouldn't be derived from? Because there are different ways.

If class A should not be an object because it's nonsensical, then A should be an abstract data type. A will only exist through its children.

If you want to prevent inheritance the path with least resistance is with a non-virtual destructor. Non-virtual destructors do not properly clean up after a derived object has been sliced, so competent programmers do not extend such classes.
__________________
Os iusti meditabitur sapientiam
Et lingua eius loquetur indicium

"There is nothing either good or bad, but thinking makes it so." (Shakespeare, Hamlet, Act II scene ii)

http://www.myspace.com/whiteflags99
whiteflags is offline   Reply With Quote
Old 07-08-2009, 12:59 AM   #8
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,359
Come to think of it, I do know a way to accomplish roughly what you want, but it requires you to switch from private inheritance to composition. You could use the pointer to an implementation (pimpl) idiom. Since you only have a forward declaration of Enemy in the header file, your users cannot do much with the Enemy class anyway, but you can do all you want in the corresponding source file.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-08-2009, 01:09 AM   #9
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
Ok. This is what I think I'll settle down with.

Code:
enum class Suit: unsigned char{SPADE,HEART,DIAMOND,CLUB};

class Cards {
	private:
		class Card: private Enemy {
			private:
				Suit value;

			public:
				Suit suit() const;
		} cards[3];

	public:
		void update();
};

Suit Cards::Card::suit() const {
	return value;
}

void Cards::update() {
	if(cards[0].suit()==cards[1].suit() && cards[1].suit()==cards[2].suit())
		delete this;
}
Tux0r is offline   Reply With Quote
Old 07-08-2009, 01:16 AM   #10
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,359
Eh, do not use delete this. I believe that it is only defined if the object was created by new, and even then the user has no way of knowing that the object has been destroyed.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is online now   Reply With Quote
Old 07-08-2009, 01:33 AM   #11
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
Three-of-a-Kind - Zeldapedia, The Legend of Zelda wiki - Twilight Princess, Ocarina of Time, Spirit Tracks, and more

That's the enemy in the game I'm writing, they come in 3 and to defeat them they should be set to the same value.

When the values of them are the same then the destructor is called. The destructor will call an event. Like, creating a chest with treasure because the enemies were defeated. I believe it makes perfect sense, and because I'm using polymorphism I have to new (afaik).

Code:
enum class Suit: char{NONE,SPADE,HEART,DIAMOND,CLUB};

class Cards: private Enemy {
	private:
		class Card: private Enemy {
			private:
				Suit value;

			public:
				Suit suit() const;
				void set_suit(Suit&&);
				void update();
		} cards[3];

	public:
		void update();
};

Suit Cards::Card::suit() const {
	return value;
}

void Cards::Card::set_suit(Suit&& val) {
	value=val;
}

void Cards::update() {
	for(int i{}; i<3; ++i)
		cards[i].update();

	//Check for equality
	if(cards[0].suit()!=Suit::NONE && cards[1].suit()!=Suit::NONE && cards[2].suit()!=Suit::NONE) {
		if(cards[0].suit()==cards[1].suit() && cards[1].suit()==cards[2].suit()) {
			delete this;
		}
		else {
			for(int i{}; i<3; ++i)
				cards[i].set_suit(Suit::NONE);
		}
	}
}
Tux0r is offline   Reply With Quote
Old 07-08-2009, 02:08 AM   #12
Registered User
 
Join Date: Apr 2006
Location: United States
Posts: 3,201
I find it weird though that when you essentially win no attempt is made to communicate the fact to the outside and your object just dies.

You should let the scope that created your object be where the object is destroyed wherever possible. Even dynamic storage tends to be managed this way. It mirrors automatic storage, which is easy to understand, and typically is well defined.
__________________
Os iusti meditabitur sapientiam
Et lingua eius loquetur indicium

"There is nothing either good or bad, but thinking makes it so." (Shakespeare, Hamlet, Act II scene ii)

http://www.myspace.com/whiteflags99
whiteflags is offline   Reply With Quote
Old 07-08-2009, 02:13 AM   #13
C++0x User
 
Tux0r's Avatar
 
Join Date: Nov 2008
Location: Sweden
Posts: 133
Ok well there's the other option of adding a bool member variable to Cards, maybe destroyed.

Then my delete loop on std::vector<Enemy*> will take care of the rest when it's time.
Tux0r is offline   Reply With Quote
Old 07-08-2009, 04:25 PM   #14
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
C++ does not have the notion of public and private classes as other languages do. If the class is in a namespace and the namespace is visible to the object then the object can use any class in the namespace - generally speaking. You cannot 'hide' classes in namespaces. The only way I know to 'hide' classes is either hide them in the impl of an interface, use pimpl (public functions operate on a private instance of the impl), or do what you have done and make the class private to another. Anytime I see a class nested in another class to me it implies the outside class has ownership of the nested class.

Another very ugly way to do this is to make a class completely private and then use friend to expose the class to any class needing to use it. Some completely dislike friend as it breaks encapsulation but in this case it is more enforcing encapsulation than breaking it. You are forcing a user of the class to access the nested class members and data via the owning class. One huge problem with friend, even when used appropriately, is that it is not inherited. So any classes derived from a base that has friends does not inherit those friends. This will break a facade pattern rather quickly and does not work well with interfaces.
__________________
If you aim at everything you will hit something but you won't know what it is.
Bubba is offline   Reply With Quote
Old 07-09-2009, 04:35 AM   #15
Registered User
 
Join Date: Jun 2005
Posts: 1,343
Quote:
Originally Posted by Bubba View Post
Some completely dislike friend as it breaks encapsulation but in this case it is more enforcing encapsulation than breaking it.
The most common reason I see for people not liking friend is that they believe encapsulation means "everything in a class is accessed via a member function". A more correct definition of encapsulation is that nothing can access private details (data or implementation) of an entity the designer specifically allows such access. A friend declaration is fully compliant with such a definition of encapsulation: it allows a programmer to explicitly grant access to private members of a class.

Quote:
Originally Posted by Bubba View Post
One huge problem with friend, even when used appropriately, is that it is not inherited.
Allowing inheritence of friendship would completely violate encapsulation (a class could receive access to private data of aniother class without knowledge of the designer of that other class).

Quote:
Originally Posted by Bubba View Post
So any classes derived from a base that has friends does not inherit those friends. This will break a facade pattern rather quickly and does not work well with interfaces.
It will break broken usages of the facade pattern. There is nothing in the facade pattern that requires the facade to be a friend. Specifically, the facade pattern is not intended as a means of circumventing access control.

Interfaces specify the semantics for usage of a class. They do not specify how compliance with the interface is implemented. Friendship simply allows a class definition to explicitly specify that other entities (eg other classes or other functions) are part of that interface.

Or, to put it another way, if inability to inherit friendship breaks the implementation of a derived class then either the design of the base class is broken (i.e. it does not provide access to capabilities required by derived classes) or the derived class implementation is trying to do something invalid (access private members of a base class without permission).

I suspect you're referring to the fact that poor design of a base can make life inconvenient for implementers of derived classes. That does not mean the derived class implementer should have access to private members of a base class that are not granted by that base class. It means the base class should be modified so it allows the derived class to perform operations it needs.
__________________
Right 98% of the time, and don't care about the other 3%.
grumpy is offline   Reply With Quote
Reply

Tags
class, namespace

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
question about a working linked list cold_dog C++ Programming 23 09-13-2006 01:00 AM
data validation & namespace tiange C++ Programming 4 07-05-2005 02:45 AM
Templated Binary Tree... dear god... Nakeerb C++ Programming 15 01-17-2003 02:24 AM
can't insert data into my B-Tree class structure daluu C++ Programming 0 12-05-2002 06:03 PM
Post programs GaPe C# Programming 8 05-12-2002 11:07 AM


All times are GMT -6. The time now is 04:38 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22