How to call base class method if it is not abstract.
class WithAbstMethod {
public:
virtual void do() = 0;
}
class WithImplMethod : public WithAbstMethod {
public:
virtual void do() {
// do something
}
}
template<typename BaseT>
class DerivedClass : BaseT {
public:
virtual void do() {
BaseT::do(); // here is a question. How to modify code, so that do() is called if it is not abstract?
// do something
}
}
void main() {
DerivedClass<WithAbstMethod> d1;
d1.do(); // only DerivedClass::do() should be called
DerivedClass<WithImplMethod> d2;
d2.do(); // both WithImplMethod::do() and DerivedClass::do() should be called
}
Is it possible to do this using templates in compile-time without much code (instantiate DerivedClass::do() method with BaseT::do() call and without depending on BaseT type)?
Obviously, provide implementation in WithAbstMethod class is not an option. Code above is pseudo-code so may contain minor errors.
Actually, providing an implementation for WithAbstMethod::do() might be an option. Abstract functions are allowed to have an implementation.
void WithAbstMethod::do()
{
// do nothing...
}
Related
Given a base class which has some virtual functions, can anyone think of a way to force a derived class to override exactly one of a set of virtual functions, at compile time? Or an alternative formulation of a class hierarchy that achieves the same thing?
In code:
struct Base
{
// Some imaginary syntax to indicate the following are a "pure override set"
// [
virtual void function1(int) = 0;
virtual void function2(float) = 0;
// ...
// ]
};
struct Derived1 : Base {}; // ERROR not implemented
struct Derived2 : Base { void function1(int) override; }; // OK
struct Derived3 : Base { void function2(float) override; }; // OK
struct Derived4 : Base // ERROR too many implemented
{
void function1(int) override;
void function2(float) override;
};
I'm not sure I really have an actual use case for this, but it occurred to me as I was implementing something that loosely follows this pattern and thought it was an interesting question to ponder, if nothing else.
No, but you can fake it.
Base has non-virtual float and int methods that forward to a pure virtual std variant one.
Two helper classes, one int one float, implement the std variant one, forwarding both cases to either a pure virtual int or float implementation.
It is in charge of dealing with the 'wrong type' case.
Derived inherit from one or another helper, and implement only int or float.
struct Base
{
void function1(int x) { vfunction(x); }
void function2(float x) { vfunction(x); }
virtual void vfunction(std::variant<int,float>) = 0;
};
struct Helper1:Base {
void vfunction(std::variant<int,float> v) final {
if (std::holds_alternative<int>(v))
function1_impl( std::get<int>(v) );
}
virtual void function1_impl(int x) = 0;
};
struct Helper2:Base {
void vfunction(std::variant<int,float> v) final {
if (std::holds_alternative<float>(v))
function2_impl( std::get<float>(v) );
}
virtual void function2_impl(float x) = 0;
};
struct Derived1 : Base {}; // ERROR not implemented
struct Derived2 : Helper1 { void function1_impl(int) override; }; // OK
struct Derived3 : Helper2 { void function2_impl(float) override; }; // OK
This uses https://en.wikipedia.org/wiki/Non-virtual_interface_pattern -- the interface contains non-virtual methods, whose details can be overridden to make them behave differently.
If you are afraid people will override vfunction you can use the private lock technique, and/or just give it a name like private_implementation_detail_do_not_implement and trust your code review process.
Or an alternative formulation of a class hierarchy that achieves the same thing?
One option is to have an intermediate base class that implements one function.
struct Base
{
virtual ~Base() {};
virtual void function(int) = 0;
virtual void function(float) = 0;
};
template <typename T>
struct TBase : Base
{
virtual void function(T) override {}
};
struct Derived1 : Base {};
struct Derived2 : TBase<float> { void function(int) override {} };
struct Derived3 : TBase<int> { void function(float) override {} };
int main()
{
Derived1 d1; // ERROR. Virtual functions are not implemented
Derived2 d2; // OK.
Derived3 d3; // OK.
}
Note that the functions are named function in this approach, not function1 and function2.
Your classes will remain abstract if you don't override all the abstract virtual methods. You have to do all of them if you want to instantiate the object.
Suppose that I have a heirarchy of several classes:
class A {
public:
virtual void DoStuff() = 0;
};
class B : public A {
public:
// Does some work
void DoStuff() override;
};
class C : public B {
public:
// Calls B::DoStuff and does other work
void DoStuff() override;
};
It can naively be implemented:
void Derived::DoStuff() {
Base::DoStuff();
...
}
This implementation has a serious problem, I believe: one always has to remember to call base implementation when overrides.
Alternative:
class A {
public:
void DoStuff() {
for (auto& func: callbacks_) {
func(this);
}
}
virtual ~A() = default;
protected:
template <class T>
void AddDoStuff(T&& func) {
callbacks_.emplace_back(std::forward<T>(func));
}
private:
template <class... Args>
using CallbackHolder = std::vector<std::function<void(Args...)>>;
CallbackHolder<A*> callbacks_;
};
Usage:
class Derived : public Base {
public:
Derived() {
AddDoStuff([](A* this_ptr){
static_cast<Derived*>(this_ptr)->DoStuffImpl();
});
}
private:
void DoStuffImpl();
};
However, I believe that it has a good amount of overhead when actually calling DoStuff(), as compared to the first implementation. In the use cases which I saw, possibly long costruction of objects is not a problem (one might also try to implement something like "short vector optimization" if he wants).
Also, I believe that 3 definitions for each DoStuff method is a little too much boilerplate.
I know that it can be very effectively solved by using inheritance pattern simular to CRTP, and one can hide the template-based solution behind interface class (A in the example), but I keep wondering -- shouldn't there be an easier solution?
I'm interested in a good implementation of call DERIVED implementation FROM BASE, if and only if derived class exists and it has an overriding method for long inheritance chains (or something equivalent).
Thanks!
Edit:
I am aware of an idea described in #Jarod42's answer, and I don't find it appropriate because I believe that it is ugly for long inheritance chains -- one has to use a different method name for each level of hierarchy.
You might change your class B to something like:
class A {
public:
virtual ~A() = default;
virtual void DoStuff() = 0;
};
class B : public A {
public:
void DoStuff() final { /*..*/ DoExtraStuff(); }
virtual void DoExtraStuff() {}
};
class C : public B {
public:
void DoExtraStuff() override;
};
I am not sure if I understood correctly but this seems to be addressed pretty good by the "Make public interface non-virtual, virtualize private functions instead" advice.
I think it's orignated in the Open-Closed principle. The technique is as-follows:
#include <iostream>
class B {
public:
void f() {
before_f();
f_();
};
private:
void before_f() {
std::cout << "will always be before f";
}
virtual void f_() = 0;
};
class D : public B{
private:
void f_() override {
std::cout << "derived stuff\n";
}
};
int main() {
D d;
d.f();
return 0;
}
You essentially deprive descendant class of overriding public interface, only customize exposed parts. The base class B strictly enforces that required method is called before actual implementation in derived might want to do. As a bonus you don't have to remember to call base class.
Of course you could make f virtual as well and let D decide.
Is there a way to force implementation of a method in a child class where the implementation will have a different signature for each derived class?
I know I can do this, using pure virtual:
class Base {
public:
virtual void getValue(string& s) = 0;
}
class Derived : public Base {
public:
void getValue(string& s);
}
Above, pure virtual getValue in the base class forces the derived class to implement getValue. But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature:
class Base {
public:
void getValue() = 0;
}
class Derived_A : public Base {
public:
void getValue(string& s);
}
class Derived_B : public Base {
public:
void getValue(int *j);
}
The problem with the above is that, due to name mangling, each signature is effectively a different function, and thus Derived_A and Derived_B inherit getValue() = 0 and the compiler thinks that they also are abstract.
I've been playing around with some different ways to do this, but it appears to me there is no way to do it. I'm thinking I should simply not declare getValue in the Base class and then just make sure each derived class implements their version of it.
If use of CRTP would work for you, you can use:
#include <string>
template <typename TypeSelector>
class Base {
public:
using type = typename TypeSelector::type;
virtual void getValue(type t) = 0;
};
struct TypeSelector_A {
using type = std::string&;
};
class Derived_A : public Base<TypeSelector_A> {
public:
void getValue(std::string& s) { /* Add real implementation */ }
};
struct TypeSelector_B {
using type = int*;
};
class Derived_B : public Base<TypeSelector_B> {
public:
void getValue(int* j) { /* Add real implementation */ }
};
int main()
{
Derived_A a;
Derived_B b;
}
But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature
The whole point of having virtual function (abstract or not) is that you can use it with pointer or reference to the base class which means you would use signature of the function from the base class. With that having what you want is completely useless. What you want can be implemented by returning std::variant or std::any with every virtual function in tree so keeping signature the same.
You should think how would you use such concept if it would be possible. If you think somethink like this:
void foo( Base *b ) {
if( auto *d = dynamic_cast<Derived_A *>( b ) ) {
std::string str;
d->getValue( str );
...
}
if( auto *d = dynamic_cast<Derived_B *>( b ) ) {
int i = 0;
d->getValue( &i );
...
}
}
then getValue() does not need to be virtual, you only need vritual destrictor in Base. But this is considered bad design.
Why I can't create new instance of class which is derived class of my abstract base class? My derived class has overriden base method but with different parametr which is derived class of base class param.
class BaseArg {
} ;
class DerivedArg :public BaseArg{
} ;
class BaseHandler{
public:
virtual void handle(BaseArg* arg) = 0;
} ;
DerivedHandler {
void handle(DerivedArg* arg) {}
} ;
auto x = new DerivedHandler() ;
Compiler returns "Cannot Instantiate abstract class"
Why? In my opinion it should works.
class BaseHandler
{
public:
virtual void handle(BaseArg* arg) = 0;
};
You declare a virtual function handle that needs to be able to accept any kind of BaseArg.
class DerivedHandler : public BaseHandler
{
public:
void handle(DerivedArg* arg) { }
};
Your overriding function just accepts one specific type of BaseArg, so it does not suffice to provide an implementation for the (more general!) inherited function handle. The other way round would have worked (in theory only, see below) – or it would have (truely) worked with return type, as a DerivedArg returned always is a BaseArg, too...
For overview:
class Base
{
public:
virtual void f0(BaseArg* arg) = 0;
virtual void f1(DerivedArg* arg) = 0;
virtual BaseArg* f2() = 0;
virtual DerivedArg* f3() = 0;
};
class Derived : public Base
{
public:
virtual void f0(DerivedArg* arg) override; // FAILS!
virtual void f1(BaseArg* arg) override; // (fine...)(*)
virtual DerivedArg* f2() override; // fine...
virtual BaseArg* f3() override; // FAILS!
};
(*) Actually, this case would have been fine in theory. C++, however, does not support contravariant function arguments, so this case will fail, too (the new function considered being an overload only)!
For more information, have a look at Wikipedia.
I have cumbersome class and I want to refactor it to replace type code with subclasses. At some point during such process I have following hierarchy:
// interface
ISomeClass(){
public:
virtual foo() = 0;
virtual ~ISomeClass();
}
// this class is cumbersome one with huge amount of conditional logic based on type
BaseSomeClass : public ISomeClass(){
public:
virtual foo(){
if(TYPE_0 == getType()){ // finally I want to move such conditional logic in subclass
doSmth();
} else if (TYPE_1 == getType()){
doAnother();
}
}
protected:
virtual int getType(){ // I temporary need it for refactoring issue
return type_; // to replace type_ with subclasses
}
private:
int type_;
};
// this classes is almost empty now, but I want to move there all conditional logic in future
class Implementation1 : public BaseSomeClass {
virtual int getType(){ // I temporary need it for refactoring issue
return TYPE_0; // to replace type_ with subclasses
}
};
class Implementation2 : public BaseSomeClass {
virtual int getType(){ // I temporary need it for refactoring issue
return TYPE_1; // to replace type_ with subclasses
}
};
In BaseSomeClassdefined additional virtual method getType(). Would this method behavior be polymorphic if I handle all the instances using some kind of interface ISomeClass pointer? Assuming the interface itself doesn't provide such virtual method. Please notice this code is a first step in refactoring, not final one. Also this is a simplified example and real code has tens of such methods, I need to do refactoring step by step. And the question is about C++ dynamic polymorphism.
You asked:
Would this method behavior be polymorphic if I handle all the instances using some kind of interface ISomeClass pointer? Assuming the interface itself doesn't provide such virtual method.
If the interface does not provide such a virtual method, you can't expect polymorphic behavior.
It'll be better to implement foo in Implementation1 and Implementation2.
class BaseSomeClass : public ISomeClass()
{
};
class Implementation1 : public BaseSomeClass
{
virtual void foo()
{
doSmth();
}
};
class Implementation2 : public BaseSomeClass
{
virtual void foo()
{
doAnother();
}
};
If you must use getType(), you can resort to template based polymorphic behavior.
template <typename D>
class BaseSomeClass : public ISomeClass()
{
public:
virtual foo()
{
int type = D::getType();
if(TYPE_0 == type)
{
doSmth();
}
else if (TYPE_1 == type)
{
doAnother();
}
}
};
Here, you are expecting D to provide the interface getType(). You might as well expect D to provide the interface foo.
template <typename D>
class BaseSomeClass : public ISomeClass()
{
public:
virtual void foo()
{
D::foo():
}
};