Given an abstract base class with a protected member, how can I provide read access only to derived classes?
To illustrate my intention I provide a minimal example. This is the base class.
class Base
{
public:
virtual ~Base() = 0;
void Foo()
{
Readonly = 42;
}
protected:
int Readonly; // insert the magic here
};
This is the derived class.
class Derived : public Base
{
void Function()
{
cout << Readonly << endl; // this should work
Readonly = 43; // but this should fail
}
};
Unfortunately I cannot use a const member since it have to be modifiable by the base class. How can I produce the intended behavior?
The usual way to do it is to make your member private in the base class, and provide a protected accessor:
class Base
{
public:
virtual ~Base() = 0;
void Foo()
{
m_Readonly = 42;
}
protected:
int Readonly() const { return m_Readonly; }
private:
int m_Readonly;
};
As protected member is visible in derived class, if you want the member to be readonly in derived class, you can make it private, and provide a getter function.
class Base {
public:
Base();
virtual Base();
public:
int getValue() {return value;}
private:
int value;
}
This way you can still change the value in base class, and it's readonly in children class.
Best-practice guidelines for inheritance should be to always make member variables private and accessor functions public. If you have public functions that you only want called from derived classes it means you are writing spaghetti code. (source: Meyer's Effective C++ item 22)
Related
If I inherit a derived class privately from a base class, I cannot get the polymorphism of the inhritetted class.
But I can get the polymorphism of 'this' pointer inside the derived class.
I'm very curious about why 'this' pointer is allowed to polymorphism to its private parent, however, a pointer outside of the class is not.
Thanks in advance!
#include <iostream>
class Shape
{
public:
virtual void say() const = 0;
virtual void who()
{
std::cout << "Shape" << std::endl;
}
void whoAmI() {
this->who();
}
};
class Squire : private Shape
{
public:
virtual void say() const
{
std::cout << "Squire" << std::endl;
}
void doSay()
{
// why this pointer to Shape type is allowed in class?
privateSay(this);
}
private:
void privateSay(Shape* s)
{
s->say();
}
};
void say(Shape* s)
{
s->say();
}
int main(int argc, const char * argv[]) {
// insert code here...
Squire* s = new Squire();
// allowed
s->doSay();
// not allowd, compile errors
// Cannot cast 'Squire' to its private base class 'Shape'
say(s);
return 0;
}
=========
Edit to clarify.
Thanks for all the answers.
To clarify my question, I think if C++ allows this behavior, mybe it violates the encapsulation a little.
A clearer case:
#include <iostream>
class Base
{
public:
void baseFunc() const
{
std::cout << "baseFunc" << std::endl;
}
};
class Worker
{
public:
Worker(Base *pBase)
{
base_ = pBase;
}
void breakFunc() const
{
base_->baseFunc();
}
private:
Base *base_;
};
class Derived : private Base
{
public:
void init()
{
worker_ = new Worker(this);
}
Worker* getWorker()
{
return worker_;
}
private:
Worker *worker_;
};
int main()
{
Derived derived;
derived.init();
Worker *worker = derived.getWorker();
worker->breakFunc();
}
The object of Base class only exisits in the object of Derived class as the parent object part, however, the Derived class inheritents Base class privately, which means the object of the Derived class has-an object of the Base class, privately.
The code above violates the encapsulation rule of the Derived class, however, even no warnning is given during compilation.
In my opinion, an explicit cast should be used under the circumstances,or an warning should be given during compilation.
The question asked here is why a base class is accessible when privately inherited.
The answer is rather simple: Because base classes are always visible to inherited regardless of the type of inheritance.
You can static_cast to a base class when the base is visible within the context.
class base
{
};
class inherited : base
{
public:
void foo()
{
// works, base is visible within the method.
auto pBase = static_cast<base*>(this);
}
};
int main() {
inherited i{};
// auto pBase = static_cast<base*>(&i); // won't compile, base is not visible
return 0;
}
Private inheritance means that both public and protected symbols from the base class become private symbols of the derived class. private symbols of the base class are inaccessible to the derived class. With exception of private virtual methods which can still be overridden.
this pointers, or in general Class* ptr used inside the class, can access private fields of the class.
Since the symbol Shape::say is public in Shape, it becomes private in Squire(BTW Did you mean Square?). This prevents its usage by public but not by this. Due to rules of virtuals, this "privatizes" the whole chain of overridden methods.
void Squire::privateSay(Shape* s)
{
// Works because `Shape::say` is a public symbol of Shape -> private symbol of Squire and `this` can access private symbols.
s->say();
}
void say(Shape* s)
{
// Shape::say is a private symbol, obviously cannot be called.
s->say();
}
If there existed private Shape::foo() method, it would not be accessible even through this in any of the Squire's methods.
The following example is from the book "Inside C++ object model"
class Abstract_base {
public:
virtual ~Abstract_base () = 0;
virtual void interface () const = 0;
virtual const char* mumble () const
{
return _mumble;
}
protected:
char *_mumble;
};
The author says if I want to initialize _mumble, the data member of the pure virtual base class, a "protected constructor" should be implemented.
But why protected? And why "public constructor" is not suitable for this class?
Thanks for your answers, and it would be perfect if there's an example.
It doesn't really matter, since you're not allowed to construct objects of the base class anyway. Making it protected serves only as a reminder of the fact that the class is supposed to be a base class; it's only cosmetics/documentation.
Consider
struct Base {
virtual ~Base() = 0;
protected:
Base() { std::puts("Base constructor"); }
};
Base::~Base() { std::puts("Base destructor"); }
struct Derived : Base {};
int main()
{
//Base b; // compiler error
Derived d;
Base *b = new Derived();
delete b;
}
Removing the protected doesn't change the meaning of the program in any way.
Abstract classes and construction of such
It doesn't matter if the constructor is public or protected, since an abstract class cannot be instantiated.
You must inherit from it in order to have it's constructor called, and since the Derived class calls the constructor of the abstract class it doesn't matter what protection level you choose, as long as the Derived class can access it.
One reason that one could possibly have for making it protected is to serve as a reminder that the class must be constructed through inheritance, but honestly that should be clear enough when seeing that it has pure virtual member-functions.
example snippet
struct B {
virtual void func () = 0;
virtual ~B () = 0 { };
};
B::~B () { }
struct D : B {
void func () override;
};
int main () {
B b; // will error, no matter if Bs ctor is 'public' or 'protected'
// due to pure virtual member-function
D d; // legal, D has overriden `void B::func ()`
}
A pure virtual class cannot be instantiated, so it doesn't make a difference if the constructor is public or protected.
A public constructor is syntactically correct. However, making it protected will carry a stronger indication that the class cannot be instantiated.
For an example: http://ideone.com/L66Prq
#include <iostream>
using namespace std;
class PublicAbstract {
public:
PublicAbstract() { }
virtual void doThings() =0;
};
class ProtectedAbstract {
protected:
ProtectedAbstract() { }
public:
virtual void doMoreThings() =0;
};
class B: public PublicAbstract {
public:
void doThings() { }
};
class C: public ProtectedAbstract {
public:
void doMoreThings() { }
};
int main() {
B b;
C c;
return 0;
}
A public constructor would not be very useful, since abstract classes cannot be instantiated in the first place.
A protected constructor makes sense: this way, a derived concrete class can provide its own public constructor that chains to the protected constructor of the base abstract class.
Protecetd ctor will make sure the ctor gets called by only the classes which derive from Abstract_base.
Public ctor is not suitable because the class contains a pure virtual method! How are you planning to instantiate a pure-virtual class if not via its child classes?
I'm stuck with a c++ problem. I have a base class that has a self referential object pointer inside the private visibility region of the class. I have a constructor in the base class that initializes these two pointers. Now I have my derived class whose access specifier is private(I want to make the public member functions of my base class private). Now through the member functions of my derived class I want to create an object pointer which can point to the private data of the base class, that is ,those self referential object pointers. My code is:
class base{
private:
base *ptr1;
int data;
public:
base(){}
base(int d) { data=d }
};
class derived:private base{
public:
void member()
};
void derived::member()
{
base *temp=new base(val); //val is some integer
temp->ptr1=NULL; //I can't make this happen. To do this I had to declare all the
//private members of the base class public.
}
Derived class can not access the private members of it's base class. No type of inheritance allows access to private members.
However if you use friend declaration you can do that.
There is no other way to access other class's private data then friendship. What you can do with inheritance, however, is to access protected data of the base class. But it doesn't mean you can access protected data of another object of the base type. You can only access protected data of the base part of the derived class:
class base{
protected: //protected instead of private
base *ptr1;
int data;
public:
base(){}
base(int d) { data=d; }
};
class derived:private base{
public:
void member();
};
void derived::member()
{
base *temp=new base(3);
//temp->ptr1 = 0; //you need friendship to access ptr1 in temp
this->ptr1 = 0; // but you can access base::ptr1 while it is protected
}
int main(){}
try to give protected as the access specifier in base class and inherit the base class in private mode.....but for further using member functions of base class u may need few short inline functions as they will also be converted to private
Well I think, you were trying to achieve a result like this!! This does not report any compiler error or such. Good luck!!!
class base{
private:
base *ptr1;
int data;
public:
base(){}
base(int d) { data=d; }
base* getPtr(); //getter to get access to base pointer
void setPtr(base* val); // setter to set value of the pointer variable
};
base* base::getPtr()
{
return ptr1;
}
void base::setPtr(base* val)
{
ptr1 = val;
}
class derived:private base{
private:
base* getPtr();
void setPtr(base* val);
public:
void member();
};
base* derived::getPtr()
{
return base::getPtr(); //derived version just invokes the base class version
}
void derived::setPtr(base* val)
{
base::setPtr(val); //derived version just invokes the base class version
}
void derived::member()
{
base *temp=new base(5); //put in a random number here instead of val
temp -> setPtr(nullptr);
}
I disagree with some of the other answers claiming the only way to access the private member is by making it a friend.
You can directly access the private member via its address in memory. If you're comfortable with it that is. You could have a function in the base class that returns the address of the private member and then use some wrapping function in the derived class to retrieve, dereference and set the private member.
I have 6 classes which all perform the same actions. I would like to move common behavior to a common [base] class.
There are actions to be performed on 6 separate objects. The six objects are located in derived classes. Intuitively, the private member objects would be accessed through the child (derived class) in the base class.
What is the C++ pattern I am looking for?
class Base
{
// Common behavior, operate on m_object
...
void Foo()
{
m_object.Bar();
}
};
class Derived1 : public Base
{
// No methods, use Base methods
private:
MyObject1 m_object;
}
class Derived2 : public Base
{
// No methods, use Base methods
private:
MyObject2 m_object;
}
The thing that is boxing me into this situation is MyObject1, MyObject2, etc offer Bar(), but don't share a common base class. I really can't fix the derivation because the objects come from an external library.
If they are introduced in the derived classes, then the base class cannot directly access them. How would the base class know that all derived classes have a specific member?
You could use virtual protected methods like so:
class my_base
{
protected:
virtual int get_whatever();
virtual double get_whatever2();
private:
void process()
{
int y = get_whatever();
double x = get_whatever2();
//yay, profit?
}
}
class my_derived_1 : my_base
{
protected:
virtual int get_whatever()
{
return _my_integer;
}
virtual double get_whatever2()
{
return _my_double;
}
}
Another possibility (if you want to call the base methods from the derived classes) is to simply supply the arguments to the base methods.
class my_base
{
protected:
void handle_whatever(int & arg);
};
class my_derived : my_base
{
void do()
{
my_base::handle_whatever(member);
}
int member;
};
C++ does and doesn't. It has a very powerful multiple inheritance support, so there is no super keyword. Why? Imagine that your base class is, say, inherited by another two classes, or even is a part of virtual inheritance hierarchy. In that case you can't really tell what super is supposed to mean. On the other hand, there are virtual methods, you can always have them in base class and implement in derived classes (that's what languages like Java do, except that they they don't have multiple class inheritance support). If you don't want to go with polymorphism, you can use something like this:
#include <cstdio>
template <typename T>
struct Base
{
void foo ()
{
std::printf ("Base::foo\n");
static_cast<T *> (this)->bar ();
}
};
struct Derived : Base<Derived>
{
void bar ()
{
std::printf ("Derived::bar\n");
}
};
int
main ()
{
Derived d;
d.foo ();
}
This is an extremely simple example - you can extend the above example with access control, friends, compile-time assertions etcetera, but you get the idea.
Have you considered not using inheritance?
class FooBar
{
MyObject m_object;
public:
FooBar(MyObject m): m_object(m) {}
//operate on different m_objects all you want
};
What about deriving your six separate objects from a common base class? Then you can declare virtual methods in that base class to create your interface, and then implement them in the derived object classes.
Maybe you just need a template instead of superclass and 6 derived classes?
It seems that you need to access not the parent's, but child's field. You should do it by introducing an abstract method:
class ParentClass
{
public:
void f();
protected:
virtual int getSomething() = 0;
};
ParentClass::f()
{
cout << getSomething() << endl;
}
class DerivedClass : public ParentClass
{
protected:
virtual int getSomething();
}
DerivedClass::getSomething() { return 42; }
If you need to access parent's method, just use ParentClass::method(...):
class ParentClass
{
public:
virtual void f();
};
class DerivedClass : public ParentClass
{
public:
virtual void f();
};
void DerivedClass::f()
{
ParentClass::f();
}
It's easy to understand the virtual function in public inheritance. So what's the point for virtual function in private or protected inheritance?
For example:
class Base {
public:
virtual void f() { cout<<"Base::f()"<<endl;}
};
class Derived: private Base {
public:
void f() { cout<<"Derived::f()"<<endl;}
};
Is this still called overriding? What's the use of this case? What's the relationship of these two f()?
Thanks!
Private inheritance is just an implementation technique, not an is-a relationship, as Scott Meyers explains in Effective C++:
class Timer {
public:
explicit Timer(int tickFrequency);
virtual void onTick() const; // automatically called for each tick
...
};
class Widget: private Timer {
private:
virtual void onTick() const; // look at Widget private data
...
};
Widget clients shouldn't be able to call onTick on a Widget, because that's not part of the conceptual Widget interface.
Your f() method is still overridden. This relationship is useful when implementing the Template Method design pattern. Basically, you'd implement common sets of operations in the base class. Those base class operations would then invoke a virtual method, like your f(). If the derived class overrides f(), the base class operations end up calling the derived version of f(). This allows derived classes to keep the base algorithm the same but alter the behavior to suit their needs. Here's a trivial example:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f() { cout<<"Base::f()" << endl; }
protected:
void base_foo() { f(); }
};
class DerivedOne: private Base
{
public:
void f() { cout << "Derived::f()" << endl;}
void foo() { base_foo(); }
};
class DerivedTwo: private Base
{
public:
void foo() { base_foo(); }
};
int main()
{
DerivedOne d1;
d1.foo();
DerivedTwo d2;
d2.foo();
}
Here's the result at run-time:
$ ./a.out
Derived::f()
Base::f()
Both derived classes call the same base class operation but the behavior is different for each derived class.
There doesn't need to be a point to every combination of different features. You're simply allowed to combine them.
A virtual protected member is accessible to derived classes, so it's useful to them.
A virtual private member is accessible to friend classes, so it's useful to them.
Both private and protected inheritance allow overriding virtual functions in the private/protected base class and neither claims the derived is a kind-of its base.
Protected inheritance allows derived classes of derived classes to know about the inheritance relationship and still override the virtual functions.
Privately inheriting from the Base class in your Derived class, destroys all conceptual ties between the derived and base class. The derived class is just implemented in terms of the base class, nothing more. Private inheritance is just an implementation technique and implies no relationship between the classes involved.
An example would be:
/// Thread body interface
class runnable
{
public:
virtual ~runnable() {}
virtual void run() =0;
};
/// Starts OS thread, calls p->run() in new thread
thread_id start_thread( runnable* p );
/// Has a private thread
class actor: private runnable, private noncopyable
{
private:
thread_id tid; /// private thread
public:
actor() { tid = start_thread( this ); } // here this IS-A runnable
// ...
virtual ~actor() { stop_thread( tid ); }
private:
virtual void run() { /* work */ }
};