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.
Related
I would like to create a thin host class of a specific class to extend a specific functionality but not necessarily inheriting it. For example, class Base is described as:
class Base
{
public:
void func_1();
void func_2();
...
void func_n();
};
class Base1 will inherit Base but store a pointer of Base
class Base1 : public Base
{
public:
void func_1()
{
mpBase->func_1();
// do something else
}
private:
Base* mpBase;
}
Is there a way to automatically invoke mpBase->func_2 to func_n for Base1 because they are basically the same (n can be a large number)? Using pointer it is not done automatically. The reason I want to do it because I want to extend func_1 for all possible inherited classes of Base, without creating Base1 for every inherited classes.
Best
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)
{
}
};
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.
I have a class Base1 that contains an array of objects of a different class Base2. I would like to have a derived class Derived1 that inherits everything from Base1 except the array is of type Derived2 (which is a derived class of Base2). For example, something like this:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
My understanding is that in the above example, an object of Derived1 would actually have TWO arrays:
list
and
Base1::list
which I don't want.
The idea is that all the functionality of Base1 should still work for a Derived1 object since Derived2 "is a" Base2. It would be really dirty, but I guess I could just delete[] the Base1::list array in the Derived1 constructor.
Does anyone see a solution to this? It seems like something that would happen frequently, and I cannot believe a simple solution does not exist. Would using templates work? My thought was no, since all the functionality in Base1 and Derived1 need to know that they are dealing with Base2 and Derived2 objects, respectively.
What do you expect to happen when someone downcasts a Derived1 class to Base1? It will crash when list is used after you sabotage the base class. The best thing is to continue to use the base class's list, and make sure only objects of type Derived2 are put in the list. If the content of the list can't be externally modified, that would work and be safe.
Yes, I know there's a lot more to say about this but let's take it one step at a time.
What you are trying to do, in general case, seems dangereous, but I assume you know the risks ;)
I can suggest two solutions:
Option 1:
You can hide the actual pointer in a protected section and provide an access function.
class Base1 {
protected:
void *ptr
public:
Base2 *list() {return (Base2*)ptr;}
};
class Derived1 : public Base1 {
public:
Derived2 *list() {return (Derived2*)ptr;}
};
Basically, the Base2::list will be hidden by the Derived2::list. Note, you cannot make them virtual and benefit from the virtuality. The return type has to be known at compile-time.
Option 2:
You can use templated base class.
template <typename T>
class List {
public:
T *list
//implement all functionality which is common, regardless of the type T
};
class Base1 : public List<Base2> {
//specifics for Base2 type
};
class Derived1 : public List<Derived2> {
//specifics for Derived2
};
Note that in this construct, Base1 and Derived1 are not directly related, but have a common ancestor instead.
I'd remove the array of Base2 from Base1, and create a new class with the list:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
};
class Base1WithList : public Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
I dont think there exists anything simple that solves your problem.
I would have used one of the following ways -
OPTION 1
Hide the Base2* list (in base1 class) by making it private, and save it getting inherited by the derived class (derived1). And of course, define a getter function in base1 class to access the list.
OPTION 2
Just change the type of list in base1 class to (a pointer to) Derived2 , and rely on the fact that a pointer to a derived class is type-compatible with a pointer to its base class.
OPTION 3
Forget inheritance and use templates. You will just need to specify the type (Base2* or Derived2*) while instantiating an object, and life will be beautiful again.
The question comment from #ildjarn gave me the solution to a similar problem:
class Base {
Base* children;
};
class Derived : public Base {
int answer;
public:
void give_answer() {
this->answer == 42;
for(auto child : this->children) {
// at this point `give_answer` is not defined for items of `children`
child->give_answer(); // -> error: ‘class Base’ has no member named ‘give_answer’
}
};
};
The solution is to introduce a virtual function into Base:
class Base {
Base* children;
public:
virtual void give_answer();
}
virtual void give_answer() = 0; would also work, making Base abstract.
(This example is a bit contrived, because why even have Base, but in my use case Derived is actually Derived<T>, and Base is a whole tree implementation.)
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.