how to make derived classes access the member data and functions of each other. both classes are inherited from base class as pure abstract.
here my scenario
class Base
{
public:
virtual void do_something() = 0;
};
class Derived1 : public Base
{
public:
virtual void do_something()
{
// need to use a2
// need to use func
}
private:
int a1;
};
class Derived2 : public Base
{
public:
virtual void do_something()
{
// need to use a1
}
void func(){}
private:
int a2;
};
Probably you need to re-think your design. There will be no memory allocated to a1 for Derived2's object and similarly for a2 and Derived1. What you are asking is equivalent to saying, both cat and dog are animals, I want to use cat::whiskers in dog.
You probably need this:
class Base
{
public:
virtual void do_something() = 0;
};
class Derived : public Base
{
public:
int a1;
int a2;
void func(){}
};
class Derived1 : public Derived
{
public:
virtual void do_something()
{
// can use a2 and func here
}
};
class Derived2 : public Derived
{
public:
virtual void do_something()
{
// need to use a1
}
void func() override {}
};
Related
If i have a base class Base:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
};
And two derived classes:
class Derived1 : public Base
{
Derived1();
bool bar() override;
}
class Derived2 : public Base
{
Derived2();
std::vector<baz*> bazVector;
bool bar() override;
}
And i have a vector std::vector<Base*> mainVector which us populated like this:
mainVector.push_back(someDerivedPointer)
At some point i need to determine what object is stored: Derived1 or Derived2, so i could access Derived2->bazVector if object is Derived2
One solution is trying to dynamic_cast<Derived2>(mainVector.at(someIndex)) and check for returned nullptr, or storing some enum that would tell me what class this object belongs to, but these solutions seem crutchy, and i wonder if there is a better solution.
As advised in the comment section, you are probably looking the wrong direction.
There's high chance you are not tackling the problem with the right approach.
If you need to write different logic based on the actual derived class from a pointer, you are missing something.
We don't have too much details, but for what you said, you have two options:
1: adding a virtual method to retrieve your vector:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual std::vector<baz*> getVector() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual std::vector<baz*> getVector() override {return {};};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual std::vector<baz*> getVector() override {return bazVector;};
}
2: insert the logic where you need this vector into a virtual function (this is probably the better):
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual void doSomething() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual void doSomething() override {/*no op*/};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual void doSomething() override {/*do something with you bazVector*/};
}
The other answer is most likely the best way to go forward in OP's case, but considering how vague the question's title is, there is an alternative idiom that is sometimes useful when:
All the derived classes of Base are known ahead of time.
The derived classes are particularly heterogenous, and creating a lowest-common-denominator interface would be problematic in some way, shape, or form.
A good example of this would be an AST. clang's ASTConsumer uses a flavor of the technique.
The visitor. The basic idea is to have an external interface with virtual methods for each derived class, and have a single virtual function in Base that dispatches this to the correct function.
class Derived1;
class Derived2;
class Base {
public:
class Visitor {
public:
virtual void operator()(Derived1&) {}
virtual void operator()(Derived2&) {}
protected:
~Visitor() = default;
};
virtual void visit(Visitor& v) = 0;
virtual ~Base() = default;
};
class Derived1 : public Base
{
public:
Derived1(){}
void visit(Base::Visitor& v) override { v(*this); }
};
class Derived2 : public Base
{
public:
Derived2(){}
void visit(Base::Visitor& v) override { v(*this); }
};
// Usage example:
struct MyVisitor final : public Base::Visitor {
void operator()(Derived1& obj) override {
std::cout << "1\n";
}
void operator()(Derived2& obj) override {
std::cout << "2\n";
}
};
int main() {
std::vector<std::unique_ptr<Base>> bases;
bases.push_back(std::make_unique<Derived1>());
bases.push_back(std::make_unique<Derived2>());
MyVisitor v;
for(auto& b : bases) {
b->visit(v);
}
}
Let's see the following C++ codes.
Each inherited class has its member variables and initialization function.
These member variables are some different(almost same type) between inherited classes.
Is there any good way to move (or merge) this initialization into base class?
class Base {
public:
virtual init() = 0;
}
class A: public Base {
public:
int a1;
void init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
void init() { b1 = 1;}
}
No. Base has no knowledge of A::a1 or B::b1. More importantly it should not have any knowledge of it's subclass members as this leads to a fundamental breakdown of the encapsulation you're trying to achieve in the first place.
The best you can do is have your Base class define a virtual method for initialisation and control when that method is called. It is up to each subclass to override the method and ensure that when initialisation is needed it is performed according to each subclass's respective requirements.
One thing to note is that if your initialisation is intended to be once-off for the lifetime of each object, the the correct place to do this is using constructors as per koizyd's answer.
On a related note, I'd like to point out that what you're asking is a variation on one of the most common OO design flaws I've seen in my career.
Using inheritance for code reuse not encapsulation.
Basically you're trying to push functionality into the base class (for reuse), and all this really achieves is making the Base class large, top-heavy and unmaintainable.
In C++ we can't (almost always) create function init, we use constructors
e.g
class Base {
};
class A : public Base {
public:
int a1;
A():Base(), a1(0) {}
};
class B : public Base {
public:
int b1;
B():Base(), b1(1){}
};
Construct "child" is A():Base(),a1(0), it's initializer list (:Base(),a1(0)), which create Base object, and int b1.
You should remember about ; after class.
I'd probably structure code like this:
class Base {
public:
void init() { sub_init(); }
protected:
virtual void sub_init() = 0;
}
class A: public Base {
public:
int a1;
protected:
void sub_init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
protected:
void sub_init() { b1 = 1;}
}
The alternative of doing something like (syntax probably not correct...):
class Base {
public:
virtual void init() = 0;
protected:
void generic_init<T>(T &foo, T const &bar) { foo = bar; }
}
class A: public Base {
public:
int a1;
void init() { generic_init<int>(a1, 0); }
}
class B: public Base {
public:
int b1;
void init() { generic_init<int>(b1, 1); }
}
Looks awful to me!
Maybe you could use the template class skills to solve the problem. Like:
template <typename T> class Base {
public :
virtual void init( T t ) = 0;
};
class A: public Base<T> {
public:
T a1;
void init( T t ) { a1 = t;}
}
class B: public Base<T> {
public:
T b1;
void init( T t ) { b1 = t;}
}
You could have a try.
My question is, if I have something like
class Base {
...
public:
virtual void func();
}
void Base::func() {
//Implementation # 1
}
class Derived1 : public Base {
...
public:
void func();
}
void Derived1::func() {
//Implementation # 1
}
class Derived2 : public Base {
...
public:
void func();
}
void Derived2::func()
//Implementation # 1
}
class Derived3 : public Base {
...
public:
void func();
}
void Derived3::func() {
//Implementation # 2
}
What I'm trying to do is I want Derived1 and Derived2 to use the implementation of func() that was used in Base, but I want Derived3 to use func() a little differently. The problem is, if I make func() virtual in Base, then both Derived1 and Derived2 will need to implement it differently which I don't want. However, if I don't make it virtual, then all derived classes will have the same implantation for func(). How can I get past this problem?
A virtual function does not have to be overridden. Derived1 and Derived2 can just not redeclare func().
Only a pure virtual function (declared with = 0) must be overridden by (non-abstract) derived classes.
Edit
This will work, but unless you need more work done in the function, #Cameron's answer is the correct one.
You can call the base function from the derived function like so:
class Base
{
public:
virtual void foo() { /* Do something */ };
};
class Derived1 : public Base
{
public:
virtual void foo() { /* Do something else */ };
};
class Derived2 : public Base
{
public:
virtual void foo() { Base::foo(); /* Do something */ };
};
Have you thought to define as virtual func only in derived1 ?
The code that follows works like that ( is that what you intended ? )
#include <stdio.h>
#define X
class Base {
public:
void func();
};
void Base::func() {
printf("Base\n");
}
class Derived1 : public Base {
public:
virtual void func();
};
void Derived1::func() {
printf("derived1\n");
};
class Derived2 : public Base {
public:
};
class Derived3 : public Base {
public:
};
int main(int argc, char **argv)
{
Base b;
Derived1 d1;
Derived2 d2;
Derived3 d3;
b.func();
d1.func();
d2.func();
d3.func();
printf("hello world\n");
return 0;
}
Just call inside the func() of Derived1 and Derived2 the Base func() like this
Base::func();
Derived3 func() can have a different implementation.
Say I have an interface hierarchy :
class A
{
virtual void commonFunc() = 0;
};
class B1 : public A
{
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
Interface A only exist to avoid duplicating the commonFunc() function.
Now if I want to implement this in order to have 2 instanciatable classes ImplB1 and ImplB2 i could do :
class ImplA
{
virtual void commonFunc();
};
class ImplB1 : public ImplA
{
virtual void b1SpecificFunc();
};
class ImplB2 : public ImplA
{
virtual void b2SpecificFunc();
};
The problem with this is that it makes ImplA instanciatable, which I don't want to. I only want ImplB1 and ImplB2 to be instanciatable, because ImplA is something asbtract that only exist to have the implementation of the common function in common.
How could i design this please ? Thank you.
Interface A only exist to avoid duplicating the commonFunc() function.
You certainly mean to avoid duplicating its declaration, don't you?
class ImplA
{
virtual void commonFunc();
};
This should probably be:
class ImplA : public A
{
virtual void commonFunc();
};
And I guess the point is that ImplA actually has an implementation of commonFunc. So for the sake of this answer's brevity, let's put it into the class definition:
class ImplA : public A
{
virtual void commonFunc() {} // implementation
};
The problem with this is that it makes ImplA instanciatable.
Just make ImplA's destructor pure virtual:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc() {}
};
This will prevent instantiation even inside of derived classes' functions. For example, the following will create a compiler error:
class ImplB1 : public ImplA
{
public:
virtual void b1SpecificFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
In fact, you will not even be able to instantiate the class in its own functions:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
But seriously, this all seems pretty over-engineered. Perhaps what you really need is to make commonFunc a non-virtual protected function of A, which derived classes can then call if they need to.
Or perhaps commonFunc can just be a free-standing utility function?
You can do the following. Also, here is a SO question/answer about this.
Note: While I'm answering the question that you can do this I'm not asserting it's what you should do.
Code
#include <iostream>
class A
{
public:
virtual void commonFunc() = 0;
};
void A::commonFunc() // Pure virtual but implemented anyway
{
// Derived classes can explicitly opt-in to this implementation
std::cout << "A::commonFunc()\n";
}
class B1 : public A
{
public:
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
class ImplB1 : public B1
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b1SpecificFunc()
{
std::cout << "b1SpecificFunc()\n";
}
};
class ImplB2 : public B2
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b2SpecificFunc()
{
std::cout << "b2SpecificFunc()\n";
}
};
int main()
{
//A a; // Won't compile (as expected/desired)
ImplB1 b1;
ImplB2 b2;
b1.commonFunc();
b1.b1SpecificFunc();
b2.commonFunc();
b2.b2SpecificFunc();
return 0;
}
Output
A::commonFunc()
b1SpecificFunc()
A::commonFunc()
b2SpecificFunc()
it's pretty diffecult for me to describe my problem.
I have two classes, I would say Base_A and Derived_A. You can see from the names, the class Derived_A is derived from Base_A. Also in my program I have other two classes Base_B and Derived_B (also with inheritance). The class Base_A contains the object of Base_B, and the class Derived_A contains the object of Derived_B.
class Base_A {
public:
Base_A() {}
virtual ~Base_A() {}
Base_B b_;
Base_B* pointer_;
void init() {
b_ = Base_B();
pointer_ = &b_;
pointer_->setValue(1);
}
void print() {
pointer_->getValue();
}
};
class Derived_A: public Base_A {
public:
Derived_A() {}
virtual ~Derived_A() {}
Derived_B b_;
Derived_B* pointer_;
void init() {
b_ = Derived_B();
pointer_ = &b_;
pointer_->setValue(2);
pointer_->increaseValue();
}
};
class Base_B {
public:
Base_B() {}
virtual ~Base_B() {}
int value_;
void setValue(int value) {
value_ = value;
}
void getValue() {
cout << "Base_B: " << value_ << endl;
}
};
class Derived_B: public Base_B {
public:
Derived_B() {}
virtual ~Derived_B() {}
void increaseValue() {
value_++;
}
};
int main() {
Derived_A derived_A = Derived_A();
derived_A.init();
derived_A.print();
return 0;
}
How you can see every class of A has one object of class B and pointer to this object. My problem is, when I call the function print(), it does not take Derived_B* pointer_, but try to access Base_B* pointer_, which is not exist. How I can say in my program, that it should take the pointer according to the class? Or do I need to declarate the Base_B* pointer_ inside the Derived_A class like:
Base::pointer_ = pointer_;
Maybe is there other method or algorithm for my problem?
Thank you a lot.
"but try to access Base_B* pointer_, which is not exist"
If DerivedA does not properly initialise BaseA, then DerivedA does not meet the "isA" rule for inheritance and the design needs changed. On the face of things:
Don't re-use names in the derived class such as b_, pointer_.
Its just confusing and you gain no value.
Make init() virtual.
Have DerivedA::init() call BaseA::init() explicitly.
Make pointer_ a virtual method.
Note the use of "covariant return types" for the virtual methods.
class BaseA
{
public:
virtual BaseB* pointer() { return &b_; }
// etc.
};
class DerivedA : public BaseA
{
public:
virtual DerivedB* pointer() { return &b_; }
// etc.
};
wouldn't Base_A have a pointer to Base_B if Base_A::init() was ever called?
why wouldn't you init the base class?