I want to apply the functions from one class to the private variables from another derived class. I was hoping that this way I could avoid redefining the exact same function multiple times.
I've added an example below.
#include <iostream>
class A {
public:
void print1();
void print2();
private:
int array[3] = {1, 2, 3};
};
class B: public A {
public:
void print3();
private:
int array[3] = {4, 5, 6};
};
void A::print1() {
std::cout << this->array[0] << std::endl;
}
void A::print2() {
std::cout << this->array[1] << std::endl;
}
void B::print3() {
print1();
print2();
std::cout << this->array[2] << std::endl;
}
int main() {
B b;
b.print3(); // Output = 1 2 6, I want = 4 5 6
return 0;
}
I thought that perhaps defining the array in class A and B as public, so it would get overwritten, would work, but this did not have any effect.
CodePudding user response:
There are two solutions, related to design patterns called "Non-virtual interface" or "Template methods".
Without virtual methods: add a member which will point to the private array:
class A {
public:
A() : array(_array) {}
void print1();
void print2();
protected:
A(int array[3]) : array(array) {}
int *array;
private:
int _array[3] = {1, 2, 3};
};
class B: public A {
public:
B() : A(_array) {}
void print3();
private:
int _array[3] = {4, 5, 6};
};
Or add a virtual method, which will return the pointer:
class A {
public:
void print1();
void print2();
protected:
virtual int *array() { return _array; };
private:
int _array[3] = {1, 2, 3};
};
class B: public A {
public:
void print3();
protected:
virtual int *array() { return _array; };
private:
int _array[3] = {4, 5, 6};
};
In this second solution use array()
instead of array
in methods (std::cout << this->array()[0] << std::endl;
etc.).
CodePudding user response:
If the implementation of print1
and print2
must be in the base class, then you need some form of polymorphic access to the array associated with the object instance.
#include <iostream>
class A {
public:
void print1();
void print2();
private:
virtual const int* getArray() const { return array; };
int array[3] = {1, 2, 3};
};
class B: public A {
public:
void print3();
private:
virtual const int* getArray() const { return array; };
int array[3] = {4, 5, 6};
};
void A::print1() {
std::cout << this->getArray()[0] << std::endl;
}
void A::print2() {
std::cout << this->getArray()[1] << std::endl;
}
void B::print3() {
print1();
print2();
std::cout << this->getArray()[2] << std::endl;
}
int main() {
B b;
b.print3(); // Outputs 4 5 6
return 0;
}
CodePudding user response:
Inheritance does not work like this, you are close to get it, but your design needs a small change. What you need to do is to change your print1
and print2
functions, to receive the argument you want to print:
class A {
public:
void print1(int num);
...
private:
int array[3] = {1, 2, 3};
};
void A::print1(int num) {
std::cout << num << std::endl;
}
Then you call the print1
and print2
functions with the int
you are interested:
void B::print3() {
print1(array[0]);
print2(array[1]);
std::cout << this->array[2] << std::endl;
}
This will call those functions in your class B
with the values stored in the "override" array
, and you will have the output you are looking for:
int main() {
B b;
b.print3(); // Output = 4 5 6
return 0;
}