#include <vector>
class Bar;
class Foo
{
friend class Bar; /* 1 */
protected:
int myint;
Foo() {Foo::Foo(0);}
Foo( int anum ) {myint=anum;}
public:
int GetMyInt() {return myint;}
};
class Bar
{
protected:
std::vector<Foo> vec;
public:
void AddAFoo( int anum ) {Foo aFoo(anum); vec.push_back(aFoo);}
};
int main( void ) /* just for show */
{
return 0;
}
Couple of questions:
The declaration at /* 1 */ is correct, but my implementation accepts
friend Bar;
Was that syntatically legal back in the day? If not, why would my
implementation accept it?
The other question is about the use of friend in general here. The
idea is that only friends of Foo should be able to instantiate it and
modify its members - is that a worthy goal, and is friend the best way
to accomplish it?
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome. 11 1177
Christopher Benson-Manica wrote: #include <vector>
class Bar;
class Foo { friend class Bar; /* 1 */
protected: int myint; Foo() {Foo::Foo(0);}
That's totally wrong. Read about "calling constructors" anywhere
you can find it. If the intention is to share some code, you need
to put it in a common function and call it in both constructors.
This is not Java.
You are supposed to write
Foo() : myint(0) {}
Foo( int anum ) {myint=anum;}
Preferred form is
Foo(int anum) : myint(anum) {} public: int GetMyInt() {return myint;}
Const-correctness is something you might want here:
int GetMyInt() const {return myint;}
};
class Bar { protected: std::vector<Foo> vec;
public: void AddAFoo( int anum ) {Foo aFoo(anum); vec.push_back(aFoo);}
You could write
void AddAFoo(int anum) { vec.push_back(anum); }
and the user-defined conversion will take care of it. A temporary
will be created without an explicit declaration.
};
int main( void ) /* just for show */ { return 0; }
Couple of questions:
The declaration at /* 1 */ is correct, but my implementation accepts
friend Bar;
Was that syntatically legal back in the day? If not, why would my implementation accept it?
It probably was. If my memory serves me well, it's not any more. The other question is about the use of friend in general here. The idea is that only friends of Foo should be able to instantiate it and modify its members - is that a worthy goal, and is friend the best way to accomplish it?
First of all, if only friends [and the class members] must be able
to instantiate Foo, then you better make the constructor _private_,
not protected. Otherwise I can derive from Foo and instantiate all
I want.
Second, yes, it's a common pattern for factory classes when they are
granted extended permissions to some class so that only they can
create an instance of that class.
Victor
On Thu, 8 Jul 2004 12:43:24 +0000 (UTC), Christopher Benson-Manica
<at***@nospam.cyberspace.org> wrote: #include <vector>
class Bar;
class Foo { friend class Bar; /* 1 */
protected: int myint; Foo() {Foo::Foo(0);} Foo( int anum ) {myint=anum;}
public: int GetMyInt() {return myint;} };
class Bar { protected: std::vector<Foo> vec;
public: void AddAFoo( int anum ) {Foo aFoo(anum); vec.push_back(aFoo);} };
int main( void ) /* just for show */ { return 0; }
Couple of questions:
The declaration at /* 1 */ is correct, but my implementation accepts
friend Bar;
Was that syntatically legal back in the day? If not, why would my implementation accept it?
What is your compiler? Perhaps it is assuming a function by that name.
The other question is about the use of friend in general here. The idea is that only friends of Foo should be able to instantiate it and modify its members - is that a worthy goal, and is friend the best way to accomplish it?
I like to use friends for factory classes, and not much else. It's
certainly not necessary, but it makes some things easier at times. For
example, when you need to initialize certain members out of order, or
supply default values which cannot (easily) be done in the member
initialization list.
I'm sure there is a clever design pattern to get around this, but ...
why bother? As long as you realize that friends tend to break OOP
paradigms and encapsulation in general ... in the factory, though, I
tend to think it actually improves encapsulation and hiding of
implementation details, as long as only the factory gets to be a
friend.
--
Bob Hairgrove No**********@Home.com
Victor Bazarov <v.********@comacast.net> spoke thus: That's totally wrong. Read about "calling constructors" anywhere you can find it.
Oh, you mean like the FAQ? How quaint! (translation: I'm dumb ;()
and the user-defined conversion will take care of it. A temporary will be created without an explicit declaration.
The prevailing practice here seems to be to declare constructors
explicit...
It probably was. If my memory serves me well, it's not any more.
I love my old compiler! ;P
First of all, if only friends [and the class members] must be able to instantiate Foo, then you better make the constructor _private_, not protected. Otherwise I can derive from Foo and instantiate all I want.
Right. I misspoke - sorry.
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Bob Hairgrove <wo**************@to.know> spoke thus: What is your compiler? Perhaps it is assuming a function by that name.
Borland 5.4.1, whose name I curse regularly.
I'm sure there is a clever design pattern to get around this, but ... why bother? As long as you realize that friends tend to break OOP paradigms and encapsulation in general ... in the factory, though, I tend to think it actually improves encapsulation and hiding of implementation details, as long as only the factory gets to be a friend.
Well, in the current situation, I have a class whose sole purpose is
to be contained in a list (it doesn't have much use on its own), so I
figured making the list a friend would help hide the unnecessary
details. My boss disagreed, however... Where can I find more
information about when friend is appropriate (beyond the FAQ section)?
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Christopher Benson-Manica wrote: [...] Well, in the current situation, I have a class whose sole purpose is to be contained in a list (it doesn't have much use on its own), so I figured making the list a friend would help hide the unnecessary details. My boss disagreed, however... Where can I find more information about when friend is appropriate (beyond the FAQ section)?
Let me see... A class whose sole purpose is to be contained in
a list... Sounds useless, sorry. Could you be a bit more specific?
No, I am not asking you to reveal secrets here, but try to explain
(and probably understand along with all of us) what else this class
is used for. Inability to be instantiated is not such a strange
requirement. But could it be that you only basically need to make
your strange class a private member of the class that owns the list?
class HasTheList {
class StrangeOne {
int i;
public:
StrangeOne(int i = 0) : i(i) {}
};
std::list<StrangeOne> thelist;
public:
void store(int i) { thelist.push_back(i); }
};
Now, 'StrangeOne' exists only in the context of 'HasTheList' and
never seen or accessed from outside.
Victor
Victor Bazarov <v.********@comacast.net> spoke thus: Now, 'StrangeOne' exists only in the context of 'HasTheList' and never seen or accessed from outside.
Perhaps that's the correct option here - thanks :)
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Victor Bazarov <v.********@comacast.net> spoke thus: Let me see... A class whose sole purpose is to be contained in a list... Sounds useless, sorry. Could you be a bit more specific? No, I am not asking you to reveal secrets here, but try to explain (and probably understand along with all of us) what else this class is used for. Inability to be instantiated is not such a strange requirement. But could it be that you only basically need to make your strange class a private member of the class that owns the list?
On second thought, let me elaborate some on what's going on here.
Basically, the simple class is a record with a few integers for
members. It can convert itself to a string, and populate its data
members from a string. The list class keeps a list of simple class
instances; it also keeps a file log of what gets added to and removed
from the list. It can load itself from a file and save itself to a
file, and writes out records to a file every time a record is added or
removed. My thinking is that since the point of this arrangement is
to have a file mirror of this list of records, having a record by
itself isn't very useful - that's why I don't want it instantiated by
just anyone. Would you still use a nested class here?
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Christopher Benson-Manica wrote: Victor Bazarov <v.********@comacast.net> spoke thus:
Let me see... A class whose sole purpose is to be contained in a list... Sounds useless, sorry. Could you be a bit more specific? No, I am not asking you to reveal secrets here, but try to explain (and probably understand along with all of us) what else this class is used for. Inability to be instantiated is not such a strange requirement. But could it be that you only basically need to make your strange class a private member of the class that owns the list?
On second thought, let me elaborate some on what's going on here. Basically, the simple class is a record with a few integers for members. It can convert itself to a string, and populate its data members from a string. The list class keeps a list of simple class instances; it also keeps a file log of what gets added to and removed from the list. It can load itself from a file and save itself to a file, and writes out records to a file every time a record is added or removed. My thinking is that since the point of this arrangement is to have a file mirror of this list of records, having a record by itself isn't very useful - that's why I don't want it instantiated by just anyone. Would you still use a nested class here?
This "record" class seems completely innocuous. Why do you want to
prohibit others from being able to instantiate it? I know, I know,
you just want to keep it as simple as possible, yes?
BTW, I still don't see the big picture. Yes, you have records, yes
you have a file of them, yes, you have a cached version of that file
in memory. Is (using your terminology) the sole purpose of your
exercise to keep the cached version of that file in memory, or is
there more to it than you let on? Again, I am not asking you to
give out secrets (if they are secrets), just try to see the bigger
picture here.
Why do you need the file mirror? Does your file mirror provide the
rest of the system with some kind of interface to the file data? Is
the format of that file kept from the rest of the system or is it
known and used directly? If it's not known, then yes, a nested
(proprietary, "private") type that implements the file record format
would probably be better, following the usual "data hiding" principle.
If it's known and used directly by other parts of the system, then by
having a separate class that [also] represents the data you create
an unnecessary dependency. What if the format changes? You would
have to refactor not only the code that keeps the cached copy of the
file records, but also the rest of the system (if it accesses it as
I supposed, directly). Hint-hint...
It seems that we've transcended C++ scope here. Your questions are
more on the design side of things, and are better discussed in
comp.object newsgroup. I don't read it, but there are many very
smart people there who can help you decide. Just make sure you
describe your problem in sufficient detail.
V
Victor Bazarov <v.********@comacast.net> spoke thus: This "record" class seems completely innocuous. Why do you want to prohibit others from being able to instantiate it? I know, I know, you just want to keep it as simple as possible, yes?
I'm trying to design it well, part of which is to keep it simple :)
BTW, I still don't see the big picture. Yes, you have records, yes you have a file of them, yes, you have a cached version of that file in memory. Is (using your terminology) the sole purpose of your exercise to keep the cached version of that file in memory, or is there more to it than you let on? Again, I am not asking you to give out secrets (if they are secrets), just try to see the bigger picture here.
The main purpose is to keep a log of changes to the list as they
happen, so the system can recover from a crash should such an event
occur. The records are used to store information about users that
need to be notified about something when they log on next, so
preservation of the data is important.
Why do you need the file mirror? Does your file mirror provide the rest of the system with some kind of interface to the file data? Is the format of that file kept from the rest of the system or is it known and used directly? If it's not known, then yes, a nested (proprietary, "private") type that implements the file record format would probably be better, following the usual "data hiding" principle.
Yes, this is the situation; this is the only module that will be
dealing with this file and the data contained therein. So perhaps
you're right... although won't it make the implementation look a
little messier?
It seems that we've transcended C++ scope here. Your questions are more on the design side of things, and are better discussed in comp.object newsgroup. I don't read it, but there are many very smart people there who can help you decide. Just make sure you describe your problem in sufficient detail.
That's true... you've done such a good job so far though, I hate to
leave ;)
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Christopher Benson-Manica wrote: Would you still use a nested class here?
Given a .h file containing any number of classes, do whatever you can to
leave the minimum number of methods from all the classes public.
Some classes must befriend others, so the methods they share can remain
private.
Nesting classes is irrelevant to this question, because only the 'friend'
system can permit those classes to share private methods. But private nested
classes would be the best.
--
Phlip http://industrialxp.org/community/bi...UserInterfaces
Philip wrote: Christopher Benson-Manica wrote:
Would you still use a nested class here?
Given a .h file containing any number of classes, do whatever you can to leave the minimum number of methods from all the classes public.
Some classes must befriend others, so the methods they share can remain private.
Nesting classes is irrelevant to this question, because only the 'friend' system can permit those classes to share private methods. But private nested classes would be the best.
Private nested classes don't have to have the "outer" classes
as their friends. Only the "outer" class will have access to
any members of the nested class, so it could easily be declared
a struct, i.e. with all members "public". I used the quotes
around public because access to them is severely limited by the
fact that the class (struct) itself is a private member of the
"outer" one, thus making them not really public.
In this light, nesting is pretty much relevant, I believe.
V This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Bonzo |
last post by:
I'm trying to write a class for a smart pointer. I'm having a problem
though when trying to implement operator== with both sides being a Smart.
(Or any function that I try to bring U into.)
The...
|
by: Bryan Parkoff |
last post by:
CMain Class is the base class that is initialized in main function. CA
Class is the base class that is initialized in CMain::CMain(). CMain Class
is always public while CA Class is always...
|
by: Justin Miller |
last post by:
Ok, I tried to make that subject as descriptive as possible.
What I'm trying to do:
I'm attempting to use policies to create a generic memento (design
pattern) template. My Memento template so...
|
by: Steve Horrillo |
last post by:
I can't figure out why this script won't insert the subject in the email and
why can't I control the font and size being used? I'm not sure where to post
this. Let me know where if this is OT.
...
|
by: hartley_aaron |
last post by:
Hi,
What does it mean when VS automatically adds a line like this to code
of my form:
Friend WithEvents Label1 As System.Windows.Forms.Label
Also, I noticed a modifier property for each...
|
by: timbobd |
last post by:
I have encountered a situation that I don't understand. When I call a sub of
Friend scope (in an object with Friend scope), I am getting an error "Public
member 'subname' not found in type...
|
by: subramanian100in |
last post by:
Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
Don't use global data(use members)
Don't use global functions
Don't use...
|
by: Mike Peretz |
last post by:
I am wondering if anyone out there is trying to use friend with C#, simular
to the way C++ handles it. I wrote a blog about it and I wonder if someone
can give me some feedback.
...
|
by: Stang02GT |
last post by:
“Google Is Your Friend. Use it.”
Yes that is correct, Google is your friend. And it’s a good one. Always there when you need it, ready and willing at all hours of the day to help you out. Some...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
| |