Hi I have such an idea in my mind, but I don't know how to implement it. In my program I already have Base class, and few derived classes.
base.hpp
BaseClass {
public:
BaseClass();
virtual int getSomething(int param);
}
base.cpp
BaseClass::BaseClass(){};
int BaseClass::getSomething(int param)
{
return param * 5;
}
derived1.hpp
DerivedClass1 : public BaseClass {
public:
DerivedClass1();
}
derived2.hpp
DerivedClass2 : public BaseClass {
public:
DerivedClass1();
}
Now I use Derived or Base classes as needed.
BaseClass *c = (BaseClass *) new DerivedClass1;
cout << c->getSomething(5);
What I want is to have some type of class specific parameter in base class, which would be different for DerivedClass1 and DerivedClass2. Here is an example, how it could look like.
base.hpp
BaseClass {
public:
BaseClass();
virtual int getSomething(int param);
}
base.cpp
BaseClass::BaseClass(){};
int BaseClass::getSomething(int param)
{
return param * CLASS_SPECIFIC_PARAM;
}
Then for DerivedClass1 this CLASS_SPECIFIC_PARAM would be 5, for DerivedClass2 would be 6 or whatever.
Is this even possible to do ? What is the best approach to do this ?
You just add a parameter to your base class which children will reset on their own values:
base.hpp
BaseClass {
public:
BaseClass() : m_param(0) {};
virtual int getSomething(int param);
protected:
int m_param;
}
derived1.hpp
DerivedClass1 : public BaseClass {
public:
DerivedClass1() : m_param(5) {};
}
derived2.hpp
DerivedClass2 : public BaseClass {
public:
DerivedClass1() : m_param(6) {};
}
PS: And add a virtual destructor to your BaseClass
An alternative would be a virtual (or pure virtual function) instead of a protected member.
BaseClass {
public:
BaseClass();
virtual int getSomething(int param);
protected:
virtual int getClassSpecific() const =0;
}
//...
BaseClass::BaseClass(){};
int BaseClass::getSomething(int param)
{
return param * getClassSpecific();
}
//...
DerivedClass1 : public BaseClass {
//...
virtual int getClassSpecific() const { return 5;}
}
//.....
DerivedClass2 : public BaseClass {
//...
virtual int getClassSpecific() const { return 6;}
}
Related
I'm looking for ways to avoid the "call super" code smell. This code smell is present when a subclass is required to invoke the super class's version of a virtual function when re-implementing that function.
class Base
{
public:
virtual void foo(){ ... }
}
class Derived : public Base
{
public:
virtual void foo(){ Base::foo();// required! ... }
}
If inheritance went only a single layer deep, I could use the template method
class Base
{
public:
void foo(){ ... ; foo_impl(); }
protected:
virtual void foo_impl(){}
}
class Derived : public Base
{
protected:
virtual void foo_impl(){ ... }
}
But if I need to subclass Derived, I'm back where I started.
I'm considering a registration approach.
class Base
{
public:
Base()
{
_registerCallback( [this](){ _baseFoo(); } );
}
void foo()
{
for( auto f : _callbacks )
f();
}
protected:
void registerCallback( std::function<void()> f )
{
_callbacks << f;
}
private:
void _baseFoo() { ... }
std::list< std::function<void()> > _callbacks;
}
class Derived : public Base
{
public:
Derived()
{
_registerCallback( [this](){ _derivedFoo(); } );
}
private:
virtual void _derivedFoo(){ ... }
}
Is there a more standard approach? Any problems with or improvements to this approach?
Use of
class Derived : public Base
{
public:
virtual void foo(){ Base::foo();// required! ... }
}
is the best approach IMO. I am not sure why you would consider that "code smell".
The potential for error is higher in the last approach you suggested.
It's easier to detect a missed call to Base::foo().
If all the classed derived from Base need to implement what Base::foo() does, it's better that the common code be in Base::foo(). The derived classes simply need to make the call.
For what it's worth, we use the pattern at my work a lot and it has proven to be robust over 20+ years of usage.
You can continue using template methods all the way down if you introduce new virtual member function on each level and override it on next one:
template <typename> struct tag {};
class Base
{
public:
void foo() { ... ; foo_impl(tag<Base>{}); }
protected:
virtual void foo_impl(tag<Base>) {}
};
class Derived1 : public Base
{
protected:
virtual void foo_impl(tag<Base>) override final { ... ; foo_impl(tag<Derived1>{}); }
virtual void foo_impl(tag<Derived1>) {}
};
class Derived2 : public Derived1
{
protected:
virtual void foo_impl(tag<Derived1>) override final { ... ; foo_impl(tag<Derived2>{}); }
virtual void foo_impl(tag<Derived2>) {}
};
class Derived3 : public Derived2
{
protected:
virtual void foo_impl(tag<Derived2>) override final { ... ; foo_impl(tag<Derived3>{}); }
virtual void foo_impl(tag<Derived3>) {}
};
If you dislike tag dispatch you can just give methods different names instead, perhaps something like foo_impl_N.
I consider all this overengineering.
chris mentioned a primary concern regards childs not calling their parent's corresponding member functions, this gives an idea about fixing that part:
#include <cassert>
class Base {
public:
void foo() {
foo_impl();
assert(base_foo_called && "call base class foo_impl");
}
protected:
virtual void foo_impl() { base_foo_called = true; }
private:
bool base_foo_called = false;
};
class DerivedFine : public Base {
protected:
void foo_impl() override {
Base::foo_impl();
}
};
class DerivedDerivedFine : public DerivedFine {
protected:
void foo_impl() override {
DerivedFine::foo_impl();
}
};
class DerivedDerivedNotFine : public DerivedFine {
protected:
void foo_impl() override {}
};
int main() {
DerivedFine foo;
foo.foo();
DerivedDerivedFine bar;
bar.foo();
DerivedDerivedNotFine baz;
baz.foo(); // this asserts
}
CRTP can solve everything.
For each foo method, you implement an empty non-virtual foo_before() that does nothing in your CRTP helper.
CRTP helper takes a derived and a base. Its virtual void foo() invokes static_cast<Derived*>(this)->foo_before() then Base::foo() then after_foo().
struct Base {
virtual void foo() { std::cout << "foo\n"; }
virtual ~Base() {};
};
template<class D, class B=Base>
struct foo_helper:B {
virtual void foo() {
static_cast<D*>(this)->before_foo();
this->B::foo();
static_cast<D*>(this)->after_foo();
}
private:
void before_foo() {}; void after_foo() {};
};
struct Derived1 : foo_helper<Derived1> {
void before_foo() { std::cout << "before1\n"; }
};
struct Derived2 : foo_helper<Derived2> {
void before_foo() { std::cout << "before2\n"; }
void after_foo() { std::cout << "after2\n"; }
};
struct DoubleDerived : foo_helper<DoubleDerived, Derived2> {
void after_foo() { std::cout << "even more after\n"; }
};
int main() {
std::cout << "---- Derived1\n";
Derived1 d1;
d1.foo();
std::cout << "---- Derived2\n";
Derived2 d2;
d2.foo();
std::cout << "---- DoubleDerived\n";
DoubleDerived dd;
dd.foo();
}
Live example.
Output:
---- Derived1
before1
foo
---- Derived2
before2
foo
after2
---- DoubleDerived
before2
foo
after2
even more after
Here's an idea inspired by this answer
The idea is to use the fact that constructors and destructors of a struct / class provides a sort of "pre/post function calling" mechanism that gets inherited. So instead of doing the pre/post function calls in the virtual method itself, we can use a functor and define the pre/post function call in the constructor / destructor. That way, functors that inherit from the base functor will inherit the pre/post function call.
Code
struct BasePrePostFunctor
{
BasePrePostFunctor()
{
printf("Base pre-func\n");
}
virtual void operator()()
{
printf("Base Main func\n");
}
~BasePrePostFunctor()
{
printf("Base post-func\n");
}
};
struct DerivedPrePostFunctor : BasePrePostFunctor
{
DerivedPrePostFunctor()
{
printf("Derived pre-func\n");
}
void operator()() override
{
printf("Derived main func\n");
}
~DerivedPrePostFunctor()
{
printf("Derived post-func\n");
}
};
class BaseClass
{
public:
virtual void virtual_func()
{
BasePrePostFunctor func;
func();
}
};
class DerivedClass : public BaseClass
{
public:
void virtual_func() override
{
DerivedPrePostFunctor func;
func();
}
};
int main(int argc, char** argv)
{
DerivedClass derived;
derived.virtual_func();
};
Output
Base pre-func
Derived pre-func
Derived main func
Derived post-func
Base post-func
For code below, are there any other ways to access a method in base through interface?
struct Base {
void funct_base() {
printf("Common function for class Foo and class Bar\n");
}
};
struct IFoo {
virtual ~IFoo() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
struct Foo : public Base, public IFoo {
virtual void funct_a() {
printf("I am Foo:: funct A\n");
}
};
class IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
class Bar : public Base, public IBar {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
};
I know this can be done, but I just do not like the wrapper, it does not seem clean:
struct IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
virtual void funct_base() = 0;
};
struct Bar : public Base {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
virtual void funct_base() {
Base::funct_base();
}
};
EDIT:
The question is, there is one base class, and two different derived classes that inherit from the same base class. Is there a way to access a base class method through derived class interface without adding a base class method wrapper?
Use a abstract base class IBase with a Abstract method funct_base and make the interface class a Virtual base classes of the classes Base, IFoo and IBar:
struct IBase {
virtual void funct_base() = 0;
};
struct Base : public virtual IBase {
virtual void funct_base() override { printf("Common function for class Foo and class Bar\n"); }
};
struct IFoo : public virtual IBase {
virtual void funct_a() = 0;
};
struct Foo : public IFoo, public Base {
virtual void funct_a() override { printf("I am Foo:: funct A\n"); }
};
class IBar : public virtual IBase {
virtual void funct_a() = 0;
};
class Bar : public IBar, public Base {
virtual void funct_a() override { printf("I am Bar:: funct A\n"); }
};
I have a class hierarchy like:
class A {
list<A*> children;
public:
void update() {
do_something();
update_current();
for(auto child : children)
children->update();
}
protected:
virtual void update_current() {};
};
class B : public A {
protected:
void update_current() override {
do_something_important();
};
};
class C1 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important();
};
};
class C2 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important_2();
};
};
int main() {
A* a = new A();
//fill a's childred list somehow
while(come_condition) {
//some code
a.update();
//something else
}
return 0;
}
The question is: how can I remove duplicate B::update_current(); calls from derived classes without changing program's behaviour? Is it possible or are there no solutions except calling base class functions manually? Thank you.
You could make B's children override a different function:
class B : public A {
protected:
void update_current() override final {
do_something_important();
do_something_important_later();
};
virtual void do_something_important_later() = 0;
};
With:
class C2 : public B {
protected:
void do_something_important_later() override {
do_something_very_important_2();
};
};
I have the following problem. I have a base class and several classes inheriting from it. All those classes are sharing a very similar interface and will most probably not be required to overload most of the shared methods.
However, all of them are using different member objects that are derived from each other and share a very similar interface too.
class BaseClass
{
protected:
Com* com;
public:
void setReady()
{
com->setReady();
}
}
class DerivedClass : BaseClass
{
protected:
DerivedCom* com;
}
class Derived2Class : BaseClass
{
protected:
Derived2Com* com;
}
How can I enable DerivedClass to have setReady() run its version of com instead of the one inherited from BaseClass?
Construct your instances with different implementations of Com. (Assuming DerivedCom implements Com)
class BaseClass
{
protected:
Com* com;
public:
BaseClass(Com* c = new Com) : com(c)
{}
void setReady()
{
com->setReady();
}
}
class DerivedClass : BaseClass
{
public:
DerivedClass() : BaseClass(new DerivedCom)
{}
}
class Derived2Class : BaseClass
{
public:
Derived2Class() : BaseClass(new Derived2Com)
{}
}
A simple solution is to introduce a getCom() protected virtual function, that returns a Com* or Com&:
virtual Com* getCom()
{ return this->com; }
The child classes can override it and return their own Com-derived instance. Your setReady() function can then be implemented as:
void setReady()
{
getCom()->setReady();
}
Your com member can then be made private, btw.
The drawback with this solution is that you'll have multiple Com-derived instances in the child classes.
Maybe a class template might help you:
class BaseClass
{
protected:
Com* com;
public:
virtual void setReady()
{
com->setReady();
}
};
template<typename T>
class ComDerived : public BaseClass {
protected:
T* com;
public:
void setReady()
{
com->setReady();
}
};
class DerivedClass : public ComDerived<DerivedCom>
{
};
class Derived2Class : public ComDerived<Derived2Com>
{
};
Why not templated mother class?
template <typename T>
class BaseClass
{
protected:
T* com;
public:
void setReady()
{
com->setReady();
}
};
class DerivedClass : BaseClass<DerivedCom>
{
};
class Derived2Class : BaseClass<Derived2Com>
{
};
To build on d909b's answer, I'd do something like:
class BaseClass {
private:
virtual Com * alloc_com() {
return new Com;
}
Com * com;
public:
BaseClass() : com(alloc_com()) {}
void setReady() {
com->setReady();
}
};
class DerivedClass {
private:
virtual Com * alloc_com() override {
return new DerivedCom;
}
};
class Derived2Class {
private:
virtual Com * alloc_com() override {
return new Derived2Com;
}
};
This works as long as DerivedCom publicly inherits from Com AND when Com has a virtual destructor. If Com does not have a virtual destructor, you also need to have a virtual dealloc_com function. Otherwise, you need to use a template or CRTP pattern, and then you're limited to cases where you are able to deduce the type of the object at compile time. If you know these are your only cases though, using templates will allow you to use the interface without adding virtual function call overhead.
I can't figure out how to call a base class method from a derived class method but concurrently applying this method call at an object passed as argument.
What I mean is this:
class Animal
{
virtual void eat(Animal& to_be_eaten) = 0;
};
class Carnivores: public Animal
{
virtual void eat(Animal& to_be_eaten) { /*implementation here*/}
};
class Wolf : public Carnivores
{
virtual void eat(Animal& to_be_eaten)
{ /*call eat method(of Base class) of Base to_be_eaten here*/ }
}
I thought of something like this
dynamic_cast<Carnivores&>(to_be_eaten).eat(*this) //and got a segmentation fault
Is there any way for this to be done?
Thank you!
New edit::
Updated the code
As simple as:
class Derived : public Base {
virtual void eat(Animal& to_be_eaten) {
Base::eat(to_be_eaten);
// do anything you want with to_be_eaten here.
}
};
EDIT: This works for me:
class Animal
{
virtual void eat(Animal& to_be_eaten) = 0;
};
class Carnivores: public Animal
{
virtual void eat(Animal& to_be_eaten) { /*implementation here*/}
};
class Wolf : public Carnivores
{
virtual void eat(Animal& to_be_eaten)
{
Carnivores *c = dynamic_cast<Carnivores*>(&to_be_eaten);
if(c)
c->Carnivores::eat(*this);
}
}
Note that i had to make Base::eat public in order to call it from Derived.
If I understand correctly, what you want is not to use a virtual call on the parameter object (to_be_eaten). I think only an object can do that for himself. I don't think there's a way for other objects to do it for him.
class Base
{
public:
virtual eat(Base& to_be_eaten);
protected:
virtual callEatNonVirtual(Base& other) = 0;
};
class Derived1 : public Base
{
public:
virtual eat(Base& to_be_eaten)
{
to_be_eaten.callEatNonVirtual(*this);
}
protected:
virtual callEatNonVirtual(Base& other)
{
Base::eat(other);
}
};
class Derived2 : public Base
{
public:
virtual eat(Base& to_be_eaten)
{
to_be_eaten.callEatNonVirtual(*this);
}
protected:
virtual callEatNonVirtual(Base& other)
{
Base::eat(other);
}
};