I have a base class in C++ that has some protected member variables (although, I do not think it is relevant that it is protected vs. private in this case).
I have a derived class that derives from this base class. In it, there is a public function that creates an object of the base class and returns that object. However, in that function I need to be able to set the protected member variables into a special state.
Example:
class Base
{
protected:
int b_value;
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
I specifically only want the derived class to be able to the protected member variable. I do not want a public accessor method in the base class.
I originally tried to fix this by making the derived class's createBase() function be a friend of the Base class. Like so:
class Base
{
protected:
int b_value;
friend Base Derived::createBase();
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
As you can see, this will not compile since Derived has not been defined yet. If it matters, these two classes are defined in separate header files. I guess one way to describe this problem is a "chicken and egg" problem where one needs the other first.
I have a feeling this has to be a "I am not designing my classes correctly and need to rethink how I am doing this" but I cannot figure out how to get this to work.
You can forward declare Derived and then make it a friend in Base :
class Derived;
class Base
{
friend class Derived;
protected:
int b_value;
};
class Derived : public Base
{
public:
Base createBase()
{
Base b;
b.b_value = 10;
return b;
}
};
However this design seems seriously flawed to me as you already stated, you should probably make createBase() a static public method in your Base class and have a setter for b_value or a constructor that sets it.
Remember that right now inside createBase(), this->b_value is also available.
Related
Consider the following
class Base;
class A {
int x;
friend class Base;
};
class Base {
protected:
A a_obj;
public:
Base(){
a_obj.x; // works
}
};
class Derived : public Base {
public:
Derived(){
a_obj.x; // not accessible
}
};
I could make public getters and setters for x, or make the object public, but that is not preferrable. Assuming there is a bunch of derived classes, adding friend class Derived in class A would make the code too verbose. Is there a way to say "A is friends with class Base and all it's children"
Is there a way to say "A is friends with class Base and all it's children"
No.
What you can do is make the base a friend (as you did), and write a protected accessor in the base that the children can use to access the private member.
In short, c++ rule is that friendship is not inheritable.
To achieve what you need, you can add static protected method as accessor in a Base class.
But, if you really need to make it w/o accessors or getters
you can make it with reinterpret_cast, but it would be hack and its not recommended.
Is there a way to say "A is friends with class Base and all it's children"
No
You need to fix your design. Classes should not be granted access to members of all types derived from a base class. As per your code, I think you need to modify the private member of a class in the constructor of other class.
One possible solution is using parameterized constructor. You can call constructor of class A from classes Base and Derived.
class Base;
class A {
int x;
public:
A(int in): x(in)
{
}
};
class Base {
protected:
A a_obj;
public:
Base(int in): A(in)
{
}
};
class Derived : public Base {
public:
Derived(): Base(5)
{
}
};
Say I have a base class Base, and a derived class Derived.
class Base
{
public:
void f1(void);
...
int data1;
...
};
class Derived : Base
{
... add stuff here that's unique to Derived
};
How can Derived inherit only the functions (i.e., f1()) and NOT the data (i.e., data1) from Base?
having attribute of a base class that is not needed in derived class is a hint for bad inheritance
in your case i assume you are going to have another derived class that needs those data members, otherwise it wouldnt make sense
then why not do something like this:
class Base
{
public:
void f1(void);
...
};
class DerivedClass : Base
{
... add stuff here that's unique to Derived
};
class DerivedClass2 : Base
{
public:
int data1;
....
}
if you have more derived classes that needs those data member i suggest you to make separate base class, one for functions and one for data members.
I believe, a derived class can override only those functions which it inherited from the base class. Is my understanding correct.?
That is if base class has a public member function say, func, then the derived class can override the member function func.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
Am i right?
Edit
I have come up with a code sample after studying the answers given by SO members. I am mentioning the points which i studied as comments in the code. Hope i am right. Thanks
/* Points to ponder:
1. Irrespective of the access specifier, the member functions can be override in base class.
But we cannot directly access the overriden function. It has to be invoked using a public
member function of base class.
2. A base class pointer holding the derived class obj's address can access only those members which
the derived class inherited from the base class. */
#include <iostream>
using namespace std;
class base
{
private:
virtual void do_op()
{
cout << "This is do_op() in base which is pvt\n";
}
public:
void op()
{
do_op();
}
};
class derived: public base
{
public:
void do_op()
{
cout << "This is do_op() in derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
bptr->op(); /* Invoking the overriden do_op() of derived class through the public
function op() of base class */
//bptr->do_op(); /* Error. bptr trying to access a member function which derived class
did not inherit from base class */
return 0;
}
You can override functions regardless of access specifiers. That's also the heart of the non-virtual interface idiom. The only requirement is of course that they are virtual.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
In Java, you can't. In C++, you can.
You are correct in that to override a function in a derived class, it must inherit it from the base class (in addition, the base class function must be virtual). However you are wrong about your assumption that virtual functions are not inherited. For example, the following works well (and is actually a known idiom for precondition/postcondition checking):
class Base
{
public:
void operate_on(some thing);
private:
virtual void do_operate_on(some thing) = 0;
};
void Base::operate_on(some thing)
{
// check preconditions
do_operate_on(thing);
// check postconditions
}
class Derived: public Base
{
// this overrides Base::do_operate_on
void do_operate_on(some thing);
};
void Derived::do_operate_on(some thing)
{
// do something
}
int main()
{
some thing;
Base* p = new Derived;
// this calls Base::operate_on, which in turn calls the overridden
// Derived::do_operate_on, not Base::do_operate_on (which doesn't have an
// implementation anyway)
p->operate_on(thing);
delete p;
}
A way to see that private methods are really inherited is to look at the error messages generated by the following code:
class Base
{
private:
void private_method_of_B();
};
class Derived:
public Base
{
};
int main()
{
Derived d;
d.private_method_of_B();
d.method_that_does_not_exist();
}
Trying to compile this with g++ leads tot he following error messages:
privatemethodinheritance.cc: In function 'int main()':
privatemethodinheritance.cc:4: error: 'void Base::private_method_of_B()' is private
privatemethodinheritance.cc:15: error: within this context
privatemethodinheritance.cc:16: error: 'class Derived' has no member named 'method_that_does_not_exist'
If class Derived wouldn't inherit that function, the error message would be the same in both cases.
No You can not over ride any function in base class .
My reason for this notion is that if you define the function in derived class that has the same function signiture in base class , the base class function will become hidden for derived class .
For more information about this exciting issue just visit :
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm
It's also depends on the type of inheritance
class Derived : [public | protected | private] Base { };
In order to override a function inherited from base class, it should be both virtual, and classified as public or protected.
I have a class Derived which is derived from class Base. In Derived's function, I can access protected members of Base. E.g., I can do this.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
i = 5;
}
}
My question is, is it possible to enforce the use of scope resolution operator when accessing base class member from derived class? The reason is that I want to make it clear in the code which variables are from the base class. The enforcement is so that I won't accidentally skip the scope resolution operator (I'm careless). I prefer not to use accessors since many members from the base class are required in the Derived class, making it tedious to code. I'm using MSVC 2010 by the way.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
Base::i = 5; //enforce so that i=5 won't compile
}
}
you can simulate it by introducing another scope:
class Base {
protected:
struct Data {int i;};
Data d_Base;
};
class Derived : class Base {
void process() {
d_Base.i = 5;
}
};
You cannot do it in the base class itself, no, there is no way you could enforce that. However, I am thinking of a trick which you could do in a derived class to enforce what you want, that is, if you declare a variable with the same name i in the derived class as a member, but of type, say, MyBadType, which is just an empty type, then i in derived will refer to it and there is really nothing the user could do with it. So he will HAVE TO qualify to get the base i. But this is naturally a joke, I mean, you don't want to fatten the size of your derived class just to enforce qualified names. Your goal itself is a bit dubious.
HTH,
Armen
This question already has answers here:
Do Sub-Classes Really Inherit Private Member Variables?
(7 answers)
Closed 5 years ago.
I know that the derived class can't access the private members of the base class, so why does the derived class inherit the private members of the base class? Is there any case that it is useful?
Thanks!
The derived class needs the private members even though it can't access them directly. Otherwise it's behavior would not build on the class it is deriving from.
For example, pretend the private stuff is:
int i;
and the class has a geti() and seti(). The value of i has to be put somewhere, even if it is private,
The public and protected methods of the base class can still access private variables of the base class, and these methods are available in the derived class.
The base class can still use the private member variables & methods.
If you want the derived classes to have access to members but keep those members hidden from the outside world, make them protected:.
Here's an example to illustrate:
class Base
{
public:
Base() : val(42.0f) {};
float GetValue() const
{
return val_;
}
private:
float val_;
};
class Derived : public Base
{
public:
float ComputedValue() const
{
return GetValue() * 2.0f;
}
};
Don't forget that the base class may have methods that are not private, and thus accessible by the derived class. Those protected or public base class methods can still invoke the private base class methods. This is particularly useful if you want to lock down core functionality in the base class, such as with a Template Method design pattern implementation:
class base
{
public:
virtual ~base() { /* ... */ }
virtual void base_func() { foo_private (); }
virtual void do_func() = 0;
private:
void foo_private()
{
// pre-do_func() operations
do_func();
// post-do_function operations
}
};
class derived : public base
{
public:
void derived_func() { base_func(); }
virtual void do_func()
{
// Derived class specific operations
}
};
The reason is because derived classes have an is-a relationship to the superclass.
A derived class instantiation IS A superclass instantiation...just with more (or less due to setting some superclass functions private) stuff.
As has been outlined by other answers here, the derived class syntactically cannot access the private members of the base class; but it needs to have a copy of the same in its memory layout. Think of casting. using 'C' casting you can cast a derived to a private base. The compiler would then need the correct memory offset in order to produce a valid memory-layout for the base object.
Ex.
class Base {
public:
void printA() {
a = 10;
std::cout << a << std::endl;
}
private:
int a;
};
class Derived : private Base{
int b;
};
Derived* d = new Derived;
Base* b = (Base*)d;
b->printA();
The derived class doesn't "inherit" the private members of the base class in any way - it can't access them, so it doesn't "inherit" them.
An instance of the derived class contains instances of the private members of the base class, for obvious reasons.
So I don't even know what you mean by that question.
when derived class object is created, base class constructor is also called for base object creation. if private members of base class are not allocated memory , the base object will be incomplete.
hence derived class object inherits private members of base, as they are created during creation of base class object, but are not accessible as they are private.
Although the private members are not accessible from the base class, they are inherited by them because these properties are used by the derived class with the help of non-private functions.
Private members of the base class are not directly accessed, but derived by base class by derived class.