Board index » cppbuilder » Question about friends and functions
=?utf-8?Q?Asger_J=C3=B8rgensen?=
![]() CBuilder Developer |
=?utf-8?Q?Asger_J=C3=B8rgensen?=
![]() CBuilder Developer |
Question about friends and functions2007-10-12 03:45:04 AM cppbuilder11 Hi there I have to classes: class TFile { TFile(TFolder* aOwner, int aSize) { aOwner->IncreaseTotalSize(aSize); } }; class TFolder { protected: IncreaseTotalSize(int Value); }; I would like to give TFile acces to the function IncreaseTotalSize and only that function. Is that possible ?? If so how ?? Thanks in advance Asger |
Chris Uzdavinis
![]() CBuilder Developer |
2007-10-12 04:19:19 AM
Re:Question about friends and functions
Asger Jørgensen < XXXX@XXXXX.COM >writes:
QuoteHi there class make the declaration private but makes TFile a friend. If TFolder inherits publically from this base class, then it can "upcast" the pointer and then call through it: #include <iostream> class TIncreaseTotalSize { public: ~TIncreaseTotalSize(){} private: virtual void IncreaseTotalSize(int Value) = 0; friend class TFile; }; class TFolder : public TIncreaseTotalSize { public: private: virtual void IncreaseTotalSize(int Value) { std::cout << "Increasing size by " << Value << std::endl; } }; class TFile { public: TFile(TFolder* aOwner, int aSize) { // ************** // note: upcast conversion TFolder to TIncreaseTotalSize, // since we're a friend of the base but not the derived type. TIncreaseTotalSize * baseOwner = aOwner; baseOwner->IncreaseTotalSize(aSize); } }; int main() { TFolder folder; TFile tf(&folder, 999); } Another way is to use a helper nested class that ONLY has one member, and it is granted friendship, and that class grants friendship to your external file. It makes for a little less "pretty" syntax, though. For example: #include <iostream> // // Nobody outside TFolder can call IncreaseTotalSize // Except for friends. The only friend is IncreaseTotalSize_Access // and IT only has one friend, TFile. // class TFolder { public: class IncreaseTotalSize_Access: // ... private: friend class IncreaseTotalSize_Access; void IncreaseTotalSize(int Value); }; void TFolder::IncreaseTotalSize(int Value) { std::cout << "Increasing size by " << Value << std::endl; } //////////////////////////////////////////////////////////// // Nested CLASS : This forwards the call into the real object. // Only TFile can invoke the call() function, since the // whole class is private, and only TFile is a friend // class TFolder::IncreaseTotalSize_Access { friend class TFile; static void call(TFolder * obj, int Value) { TFolder::IncreaseTotalSize(obj, Value); } }; class TFile { public: TFile(TFolder* aOwner, int aSize) { // ugly syntax for calling the function TFolder::IncreaseTotalSize_Access::call(aOwner, aSize); } }; int main() { TFolder folder; TFile file(&folder, 999); } There are some other ways, though. For one, using a virtual function: -- Chris (TeamB); |
Remy Lebeau (TeamB)
![]() CBuilder Developer |
2007-10-12 04:58:21 AM
Re:Question about friends and functions
"Asger Jørgensen" < XXXX@XXXXX.COM >wrote in message
QuoteI would like to give TFile acces to the function { friend class TFile; protected: IncreaseTotalSize(int Value); }; TFile can then access all of TFolder's 'private' and 'protected' members. Gambit {smallsort} |
Remy Lebeau (TeamB)
![]() CBuilder Developer |
2007-10-12 05:01:54 AM
Re:Question about friends and functions
"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
QuoteOne way is to use inheritance and to make the function virtual. TFile from accessing TFolder's other private members? Gambit |
Chris Uzdavinis
![]() CBuilder Developer |
2007-10-12 08:39:31 PM
Re:Question about friends and functions
"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes:
Quote"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message The virtual interface is probably the cleanest way to give partial friendship, but other implementations also are possible, as I showed. Another technique I didn't show is using a "key" class, where the functions are public but they take a dummy key parameter, and nobody has an instance of key except for the objects or classes to which it was explicitly given. If the key type itself is a private nested type of the class, then nobody can get an instance of it unless it's explicitly given. -- Chris (TeamB); |
Chris Uzdavinis
![]() CBuilder Developer |
2007-10-12 08:54:14 PM
Re:Question about friends and functions
Chris Uzdavinis (TeamB) < XXXX@XXXXX.COM >writes:
Quote"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes: I'm trying to say that he wanted to grant a limited friendship to a class, such that it could only access a single private member, rather than all private (and protected) members. -- Chris (TeamB); |
=?utf-8?Q?Asger_J=C3=B8rgensen?=
![]() CBuilder Developer |
2007-10-13 12:44:35 AM
Re:Question about friends and functions
Thanks to all for explaining
Kind regards Asger |
Michael Harris
![]() CBuilder Developer |
2007-10-13 10:05:30 PM
Re:Question about friends and functions
might use the hack method here...
class TFolder { protected: IncreaseTotalSize(int Value); }; class TFolderHack : public TFolder // visible only to TFile { public: IncreaseTotalSize(int Value) { TFolder :: IncreaseTotalSize(Value); }; }; class TFile { TFile(TFolder* aOwner, int aSize) { ((TFolderHack *)aOwner)->IncreaseTotalSize(aSize); } }; I know.. but what can ya do ? Michael "Asger Jørgensen"wrote in message Quote
|
Chris Uzdavinis
![]() CBuilder Developer |
2007-10-15 08:28:37 PM
Re:Question about friends and functions
"Michael Harris" < XXXX@XXXXX.COM >writes:
Quotemight use the hack method here... undefined behavior (though it could end up working.) 2) Once you accept this kind of code into your codebase, it becomes difficult to know when hacks are valid and when they are inappropriate. For example, given a codebase littered with "valid" hack type-casts, when another programmer inserts a new hack-cast, you probably won't even notice, and you won't have any idea if it's valid or not. 3) Encouraging people to go around the type system makes your interfaces much harder to use. If it were conventional to cast away the privateness of members, then users of classes must worry about public and private/protected members, and are not able to simply pay attention to the public interface. That requires that peopel know implementation details about a lot more code just to be able to use it. Not good. 4) Nothing prevents other files and other classes from using your technique, so it doesn't really solve the initial question of granting access to one class to one and only one member function. Friendship is given, not taken, and the hack solution you propose is "taking" access rather than having it be given. Since it's undocumented, there is nothing in the code to indcate that the code should be allowed. In short, this wouldn't pass a code review if I were conducting it. -- Chris (TeamB); |