I have a design problem in my application. I am quite new to the concept of virtual methods, inheritance and so forth & can't get it to run properly.
This is the situation:
I have a class called UI_Brainwash (pure coincidence) in which I have nested a second class SoundReciver.
class UI_BRAINWASH : public wxDialog
{
public:
UI_BRAINWASH(wxWindow* parent,const wxString& title,double sec);
virtual ~UI_BRAINWASH();
void OnTimer(wxTimerEvent& event);
void StartLoop();
class Soundreciver : public irrklang::ISoundStopEventReceiver
{
Soundreciver();
// why is this not allowed?!
Soundreciver(UI_BRAINWASH* par){this->parent = par;}
virtual void OnSoundStopped(ISound* sound, E_STOP_EVENT_CAUSE reason, void* userData);
public: // or private: doesn't change it -> compiler still complains
UI_BRAINWASH* parent;
};
private:
wxTimer* m_timer;
Inside my Brainwash class I play a sound and once the sound has been played OnSoundStopped() is called, which is a virtual method of the abstract irrklang::ISoundStopEventReceiver Class.
http://www.ambiera.com/irrklang/docu/classirrklang_1_1_i_sound_stop_event_receiver.html
In that method I would like to start a wxTimer which is a member of the UI_Brainwash class, the problem is I can't access the variables of the class without having a handle to it (or can i ?) so I thought of writing a constructor:
Soundreciver(UI_BRAINWASH* par){this->parent = par;}
but when I compile that with VC2008 I get the following error:
UI_BRAINWASH::Soundreciver::Soundreciver' : cannot access private member declared in class 'UI_BRAINWASH::Soundreciver'
: see declaration of 'UI_BRAINWASH::Soundreciver::Soundreciver'
: see declaration of 'UI_BRAINWASH::Soundreciver'
How do I solve this conundrum?
Thank you for your time / suggestions
The message you got is not the message about accessing private variable parent, but about accessing the constructor of the Soundreceiver. You need to make your Soundreceiver constructors public.
class Soundreciver : public irrklang::ISoundStopEventReceiver
{
public:
Soundreciver();
// why is this not allowed?!
Soundreciver(UI_BRAINWASH* par){this->parent = par;}
virtual void OnSoundStopped(ISound* sound, E_STOP_EVENT_CAUSE reason, void* userData);
private: // or private: doesn't change it -> compiler still complains
UI_BRAINWASH* parent;
};
Other way would be to declare UI_BRAINWASH friend of the Soundreciver class, as Vlad pointed out.
Nested classes can access non-public members of their parents but parents cannot access children's non-public members. There are only a few ways to fix it, really. Change protection level for members you want to access (i.e. do not make Soundreciver() and OnSoundStopped() all of the sudden become private). Or use friend keyword to allow access to non-public members for certain classes and/or functions.
Related
I need to compile something like this:
struct Base {
virtual void func1()=0;
// ...
friend void Derived::func2(Base *base);
private:
int some_private;
}
struct Derived : Base {
virtual func3()=0;
// ...
void func2(Base *child) {
std::cout << child->some_private;
}
};
But I keep getting compilation error. I tried swapping structures or declaring them first, but I can't declare Derived first (because of inheritance), and I can't declare Base first (because I need to declare friend function in Derived). What to do?
You have a few basic solutions. The most obvious is to change from private to protected. In C++, protected means subclasses have access.
You can add more public (perhaps protected) accessor methods instead.
You can forward-reference the entire Derived class and friend the entire class.
Personally, I have never felt a need to use friend methods or classes, and I don't know under what circumstances I'd have to be in before I wouldn't depend on other ways to accomplish whatever I'm trying to accomplish.
For this particular solution, I'd change the access to protected.
I have an abstract class base with private member variable base_var. I want to create a derived class, which also has base_var as a private member.
To me, this seems like an obvious thing you would want to do. base is abstract so it will never be instantiated. The only time I will create a base-object is if it is actually a derived object, so obviously when I give ´base´ a private member variable, what I am really trying to do is give that variable to all of its derived objects.
However, the below diagram seems to suggest that this is not doable with inheritance?
Why not? What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
However, the below diagram seems to suggest that this is not doable with inheritance?
Correct, private members of a class can not be accessed by derived classes. If You want a member of a class to be accessible by its derived classes but not by the outside, then You have to make it protected.
Why not? What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
Even an abstract class can have member functions which act on a (private) member variable. Consider (somewhat silly example, but well):
class MaxCached
{
private:
int cache = std::numeric_limits<int>::min();
public:
bool put(int value)
{
if (value > cache)
{
cache = value;
return true;
}
return false;
}
int get() const
{
return cache;
}
virtual void someInterface() const = 0;
};
Deriving from this class gives You the functionality of the base class (put and get) without the danger of breaking it (by for example writing a wrong value to cache).
Side note: Above is a purely made up example! You shouldn't add such a cache (which is independent of Your interface) into the abstract base class. As it stands the example breaks with the "Single Responsibility Principle"!
Just because a class is abstract doesn't mean there cannot be code implemented in that class that might access that variable. When you declare an item in a class to be private, the compiler assumes you had a good reason and will not change the access just because it there is a pure virtual function in the class.
If you want your derived classes to have access to a base class member declare the member as protected.
I have an abstract class base with private member variable base_var
class foo {
public:
virtual void a_pure_virtual_method() = 0;
int get_var() { base_var; }
virtual ~foo(){}
private:
int base_var;
};
Note that a class is said to be abstract when it has at least one pure virtual (aka abstract) method. There is nothing that forbids an abstract class to have non-pure virtual or even non-virtual methods.
I want to create a derived class, which also has base_var as a private member.
class derived : public foo {};
To me, this seems like an obvious thing you would want to do.
Sure, no problem so far.
The only time I will create a base-object is if it is actually a derived object, so obviously when I give ´base´ a private member variable, what I am really trying to do is give that variable to all of its derived objects.
Still fine.
Why not?
You are confusing access rights that are display in the image you included with the mere presence of the members in the derived. The derived class has no access to members that are private in the base class. Period. This is just according to the definition of what is private.
What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
It is not useless at all. Derived classes inherit all members, they just cannot access all of them. The private stuff is there you just cannot access it directly. Thats the whole point of encapsulation. Consider this example:
class bar : public foo {
void test() {
std::cout << base_var; // error base_var is private in foo
std::cout << get_var(); // fine
}
};
Why does this compile:
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(Foo& fooBar)
{
fooBar.fooBase();
}
};
but this does not?
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(FooBase& fooBar)
{
fooBar.fooBase();
}
};
On the one hand C++ grants access to private/protected members for all instances of that class, but on the other hand it does not grant access to protected members of a base class for all instances of a subclass.
This looks rather inconsistent to me.
I have tested compiling with VC++ and with ideone.com and both compile the first but not the second code snippet.
When foo receives a FooBase reference, the compiler doesn't know whether the argument is a descendant of Foo, so it has to assume it's not. Foo has access to inherited protected members of other Foo objects, not all other sibling classes.
Consider this code:
class FooSibling: public FooBase { };
FooSibling sib;
Foo f;
f.foo(sib); // calls sib.fooBase()!?
If Foo::foo can call protected members of arbitrary FooBase descendants, then it can call the protected method of FooSibling, which has no direct relationship to Foo. That's not how protected access is supposed to work.
If Foo needs access to protected members of all FooBase objects, not just those that are also known to be Foo descendants, then Foo needs to be a friend of FooBase:
class FooBase
{
protected:
void fooBase(void);
friend class Foo;
};
The C++ FAQ summarizes this issue nicely:
[You] are allowed to pick your own pockets, but you are not allowed to pick your father's pockets nor your brother's pockets.
The key point is that protected grants you access to your own copy of the member, not to those members in any other object. This is a common misconception, as more often than not we generalize and state protected grants access to the member to the derived type (without explicitly stating that only to their own bases...)
Now, that is for a reason, and in general you should not access the member in a different branch of the hierarchy, as you might break the invariants on which other objects depend. Consider a type that performs an expensive calculation on some large data member (protected) and two derived types that caches the result following different strategies:
class base {
protected:
LargeData data;
// ...
public:
virtual int result() const; // expensive calculation
virtual void modify(); // modifies data
};
class cache_on_read : base {
private:
mutable bool cached;
mutable int cache_value;
// ...
virtual int result() const {
if (cached) return cache_value;
cache_value = base::result();
cached = true;
}
virtual void modify() {
cached = false;
base::modify();
}
};
class cache_on_write : base {
int result_value;
virtual int result() const {
return result_value;
}
virtual void modify() {
base::modify();
result_value = base::result();
}
};
The cache_on_read type captures modifications to the data and marks the result as invalid, so that the next read of the value recalculates. This is a good approach if the number of writes is relatively high, as we only perform the calculation on demand (i.e. multiple modifies will not trigger recalculations). The cache_on_write precalculates the result upfront, which might be a good strategy if the number of writes is small, and you want deterministic costs for the read (think low latency on reads).
Now, back to the original problem. Both cache strategies maintain a stricter set of invariants than the base. In the first case, the extra invariant is that cached is true only if data has not been modified after the last read. In the second case, the extra invariant is that result_value is the value of the operation at all times.
If a third derived type took a reference to a base and accessed data to write (if protected allowed it to), then it would break with the invariants of the derived types.
That being said, the specification of the language is broken (personal opinion) as it leaves a backdoor to achieve that particular result. In particular, if you create a pointer to member of a member from a base in a derived type, access is checked in derived, but the returned pointer is a pointer to member of base, which can be applied to any base object:
class base {
protected:
int x;
};
struct derived : base {
static void modify( base& b ) {
// b.x = 5; // error!
b.*(&derived::x) = 5; // allowed ?!?!?!
}
}
In both examples Foo inherits a protected method fooBase. However, in your first example you try to access the given protected method from the same class (Foo::foo calls Foo::fooBase), while in the second example you try to access a protected method from another class which isn't declared as friend class (Foo::foo tries to call FooBase::fooBase, which fails, the later is protected).
In the first example you pass an object of type Foo, which obviously inherits the method fooBase() and so is able to call it. In the second example you are trying to call a protected function, simply so, regardless in which context you can't call a protected function from a class instance where its declared so.
In the first example you inherit the protected method fooBase, and so you have the right to call it WITHIN Foo context
I tend to see things in terms of concepts and messages. If your FooBase method was actually called "SendMessage" and Foo was "EnglishSpeakingPerson" and FooBase was SpeakingPerson, your protected declaration is intended to restrict SendMessage to between EnglishSpeakingPersons (and subclasses eg: AmericanEnglishSpeakingPerson, AustralianEnglishSpeakingPerson) . Another type FrenchSpeakingPerson derived from SpeakingPerson would not be able to receive a SendMessage, unless you declared the FrenchSpeakingPerson as a friend, where 'friend' meant that the FrenchSpeakingPerson has a special ability to receive SendMessage from EnglishSpeakingPerson (ie can understand English).
In addition to hobo's answer you may seek a workaround.
If you want the subclasses to want to call the fooBase method you can make it static. static protected methods are accessible by subclasses with all arguments.
You can work around without a friend like so...
class FooBase
{
protected:
void fooBase(void);
static void fooBase(FooBase *pFooBase) { pFooBase->fooBase(); }
};
This avoids having to add derived types to the base class. Which seems a bit circular.
Following is an interface:
class SIM{
private:
//private data
public:
Send();
Display();
Recieve();
Encrypt();
};
How do I restrict access to Display() function (it has to be lie in public part) of SIM to other classes except one class (Neo etc). I don't want to use friend etc.
Edit:
I can move the display() to private , how do i allow only NEO class to access it? 0_o
You can have Display take a dummy const reference to a type that can only be created from a privately nested within the class you want to be able to make the calls. Then in order to pass that type to Display you have to be a member of that class.
But why would you do that when friend does exactly what you want?
Code example:
class AllowedCaller
{
private:
class FriendHackHelp
{
};
public:
class FriendHack
{
public:
// You can only create a FriendHack from inside this class now...
FriendHack(const FriendHackHelp&) { }
};
void run();
};
class Displayer
{
public:
void Display(const AllowedCaller::FriendHack&) { /* Whatever */ }
};
void AllowedCaller::run()
{
Displayer d;
d.Display(FriendHack(FriendHackHelp()));
}
int main()
{
return 0;
}
In C++ this is simply not possible. What you could do is to pass the Neo class as a parameter to the Display() function as a reference and you would have a similar effect.
You can also split your SIM class to 2 classes: Displayable (with Display method) and SIM (with the remaining methods). Then, when creating Neo class, simply do not extend the Displayable class.
Let me ask you a question: What exactly is neo? Is it able to be inherited from SIM? If so, make Display() protected as opposed to private.
I've been wondering about this too in the past, check these questions:
programming language with granular method and property access
a way in c++ to hide a specific function
However,i come up to terms of the idea that the only way to implement this (in c++ at least) is to create multiple interfaces for each client class, and make each interface a friend of the client class that will access it
so you need to implement all and each of the interfaces with multiple inheritance
Given that we have overloaded methods in base class, and a derived class that was inherited as private/protected.
Can we restore only one/several of the original access level of the overloaded methods?
On GCC 4.4.0 i try to put the base methods under protected access, then inherited it using private access. When i try to restore the access level to public, it works! Is this how its suppose to work? or is it a bug on the compiler? To my understanding, restoring access level shouldn't be able to be used to promote or demote a member's access level.
Code snippet :
class base {
public:
void method() {}
void method(int x) {}
protected:
void method2() {}
};
class derived : private base {
public:
base::method; // Here, i want to restore only the none parameterized method
base::method2; // method2 is now public??
};
Changing accessibility of inherited functions through a using declaration cannot be done selectively on given overload for the simple reason that a using declaration only introduces a name into the declarative region and that by definition, functions overloads share the same name.
The only alternative I see here is to use trivial forwarding functions :
class derived : private base
{
public:
void method() { base::method(); }
using base::method2; // method2 is now public
// method(int) stays inaccessible
};
I'm not quite sure I understand your second question, but yes : you can change base members accessibility in a derived class through using declarations.
You don't restore access, per se. You set access. As you are doing above, you can explicitly set the access for any method, including ones previously declared as private.
It would be impossible to prevent protected methods from being public if the derived class wanted it so, as you could just write a minor wrapper and done. private is another matter.