I know the answer to this question might be simply "No" but I'm hoping that if it is "no" then I'll get a suggestion of doing thing differently.
Consider the following:
class IFoo
{
public:
virtual void Foo() = 0;
};
class IBar : public virtual IFoo
{
public:
virtual void Bar1() = 0;
virtual void Bar2() = 0;
};
template <typename T>
class BaseFoo : public T
{
public:
virtual void Foo() override
{
std::cout << "Common behavior Foo" << std::endl;
}
};
template <typename T>
class BaseBar1 : public T
{
public:
virtual void Bar1() override
{
std::cout << "Common behavior Bar1" << std::endl;
}
};
Now in my class I want to use the base implementation for Foo and only in some conditions use the base implementation of Bar1. So naturally I inherit from BaseFoo1<BaseBar1<IBar>> and in my class's Bar1 I will call the base sometimes (or even all the times if it made sense).
class MyClass : public BaseFoo<BaseBar1<IBar>>
{
public:
void Bar1() override
{
if(SomeCondition())
{
std::cout << "MyClass Bar1" << std::endl;
}
else
{
BaseFoo<BaseBar1<IBar>>::Bar1();
}
}
void Bar2() override {}
bool SomeCondition() { return false;}
};
What I'm interested in, is knowing if there is some way to shorten the call to the base function.
I considered using decltype(this) (or std::decay<decltype(this)>) and then I search for a way to use template metaprogramming to get the base type, but I couldn't find anything useful.
1 - Is there a way to shorten the call to the templated base?
2 - Any comments on the design?
I'm using C++11 in my project, but any suggestion up to C++17 would be nice.
Related
My aim is to have a class that inherits from another class in C++ and overloads all of the parents class methods in an identical fashion.
So when a method is called some code is run, the original method is called and a bit more code is run all in the derived class overload method.
class Base
{
Base() {}
~Base() {}
void base_method()
{
// Does something.
}
}
template<class T>
class ClassWrapper : public T
{
public:
ClassWrapper(T base) : T( base ) {}
~ClassWrapper() {}
void wrap_function()
{
// multithread block {
// call base method within multithread block.
this->base_method();
// }
}
}
int main()
{
Base B;
ClassWrapper<Base> C( B );
C.base_method();
return 0;
}
Ideally nothing would be known about the base class but all of its methods could be overridden.
I'm not sure if this is even possible but if it is any suggestions would be great!
With inheritance, you might do:
class Base
{
Base() {}
virtual ~Base() {}
virtual void base_method()
{
// Does something.
}
};
class BaseWrapper : public Base
{
public:
BaseWrapper(Base base) : Bas( base ) {}
void base_method() override
{
// Some code ...
Base::base_method();
// Some code ...
}
}
int main()
{
Base B;
BaseWrapper C( B );
C.base_method();
}
Static polymorphism achieved through CRTP (Curiously Recurring Template Pattern) might be beneficial for you.
Read more about CRTP here and here.
Imagine you have a Wrapper class like:
template <typename Impl>
class Wrapper {
public:
Wrapper() {}
~Wrapper() {}
void some_preparation() {
std::cout << "Wrapper work!" << std::endl;
}
};
and then you have your actual class like:
class MyFoo : public Wrapper<MyFoo> {
public:
MyFoo() {}
~MyFoo() {}
void foo() {
Wrapper::some_preparation();
std::cout << "Derived work!" << std::endl;
}
};
and, eventually, you can use above code like:
MyFoo wrappedFoo;
wrappedFoo.foo();
The result would be:
Wrapper work!
Derived work!
Jarod's answer is a very good one for your question. However, I would like to add an answer more focused on your chosen design rather than the implementation.
Although you said that you want to "overloads all of the parents class methods in an identical fashion", your goal ("the original method is called and a bit more code is run all in the derived class overload method") indicates that it is slightly different.
The first one may indicate inheritance, but the second one may point to factory abstract design pattern (composition over inheritance):
#include<iostream>
class AbstractBar
{
public:
virtual void bar_method() = 0;
};
class Bar1 : public AbstractBar
{
public:
void bar_method() {
std::cout << "Bar 1" << std::endl;
}
};
class Bar2 : public AbstractBar
{
public:
void bar_method() {
std::cout << "Bar 2" << std::endl;
}
};
class Foo
{
public:
Foo(AbstractBar* bar_) : bar(bar_) { }
void foo_method() {
bar->bar_method();
std::cout << "Foo" << std::endl;
}
private:
AbstractBar* bar;
};
int main() {
Bar1 bar;
Foo foo(&bar);
foo.foo_method();
}
Being the output of the code:
Bar 1
Foo
Or a simplified version (based on your needs):
#include<iostream>
class Bar {
public:
void bar_method() {
std::cout << "Bar" << std::endl;
}
};
class Foo {
public:
Foo(Bar* bar_) : bar(bar_) { }
void foo_method() {
bar->bar_method();
std::cout << "Foo" << std::endl;
}
private:
Bar* bar;
};
int main() {
Bar bar;
Foo foo(&bar);
foo.foo_method();
}
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
I have something like that (simplified)
class A
{
public:
virtual void Function () = 0;
};
class B
{
public:
virtual void Function () = 0;
};
class Impl : public A , public B
{
public:
????
};
How can I implement the Function () for A and the Function() for B ?
Visual C++ lets you only define the specific function inline (i.e. not in the cpp file),
but I suppose it's an extension. GCC complains about this.
Is there a standard C++ way to tell the compiler which function I want to override?
(visual c++ 2008)
class Impl : public A , public B
{
public:
void A::Function () { cout << "A::Function" << endl; }
void B::Function () { cout << "B::Function" << endl; }
};
Thank you!
You cannot use qualified names there. I you write void Function() { ... } you are overriding both functions. Herb Sutter shows how it can be solved.
Another option is to rename those functions, because apparently they do something different (otherwise i don't see the problem of overriding both with identical behavior).
I can suggest another way to resolve this issue. You can add wrapper Typed which changes Function signature by adding dummy parameter. Thus you can distinguish methods in your implementation.
class A {
public:
virtual void Function() = 0;
virtual ~A() = default;
};
class B {
public:
virtual void Function() = 0;
virtual ~B() = default;
};
template<typename T>
class Typed : public T {
public:
virtual void Function(T* dummy) = 0;
void Function() override {
Function(nullptr);
}
};
class Impl : public Typed<A>, public Typed<B> {
public:
void Function(A* dummy) override {
std::cerr << "implements A::Function()" << std::endl;
}
void Function(B* dummy) override {
std::cerr << "implements B::Function()" << std::endl;
}
};
The benefit of such solution is that all implementation are placed in one class.
As a workaround, try
struct Impl_A : A
{
void Function () { cout << "A::Function" << endl; }
};
struct Impl_B : B
{
void Function () { cout << "B::function" << endl; }
};
struct Impl : Impl_A, Impl_B {};
If A and B are interfaces, then I would use virtual derivation to "join" them (make them overlap). If you need different implementations for your Function if called through a pointer to A or to B then I would strongly recommend to choose another design. That will hurt otherwise.
Impl "derives from" A and B means Impl "is a" A and B. I suppose you do not mean it.
Impl "implements interface" A and B means Impl "behaves like" A and B. then same interface should mean the same behavior.
In both cases having a different behavior according to the type of pointer used would be "schizophrenic" and is for sure a situation to avoid.