I get error when i try to compile this code.
class FunctionVisitor
{
public:
virtual ~FunctionVisitor() = default;
virtual void visit(SumTimer&) = 0;
virtual void visit(SumSelector&) = 0;
};
class timerVisitor : public FunctionVisitor
{
private:
std::string variableName;
std::string variableValue;
public:
timerVisitor(std::string varName, std::string varValue) : variableName(varName), variableValue(varValue) { }
virtual void visit(SumTimer& fun) override;
};
class selectorVisitor : public FunctionVisitor
{
private:
std::string variableName;
std::string variableValue;
public:
selectorVisitor(std::string varName, std::string varValue) : variableName(varName), variableValue(varValue) { }
virtual void visit(SumSelector& sel) override;
};
The reason is that i have pure virtual functions in the base class but each sub class only has defination of one function of the base class virtual function.
Can i have pure virtual functions in this case ?
Every class that inherits from abstract class in c++ and doesn't override all of its pure virtual functions is considered abstract and cannot be instantiated neither locally nor dynamically. You can either override the functions to do nothing (or return an exception)
virtual void visit(SumTimer& fun) override {}
or make the abstract class concrete and the functions do nothing by default
class FunctionVisitor
{
public:
virtual ~FunctionVisitor() = default;
virtual void visit(SumTimer&) {}
virtual void visit(SumSelector&) {}
};
What do you want to happen if you call a different function? E.g. if you call visit(SumSelector&) on a timerVisitor?
#user253751 i don't want any action in that case.
If you don't want anything to happen when the function is called but not overridden, then make the base class have a function that does nothing. Instead of
virtual void visit(SumTimer&) = 0;
write:
virtual void visit(SumTimer&) {}
Pure virtual (= 0) means that you want to force derived classes to override the function. If you don't want to do that, then don't make them pure virtual!
Related
Edit Made clear() and append() public in "ProductionNode"
I am trying to implement in C++ a similar example to the one presented at "Working effectively with Legacy code" page 359, the resulting diagram class at page 361.
It uses multiple inheritance; there is a base class "ProductionNode" which fully implements an interface called "Node", a second base class called "ProductionModelNode" which inherits from "ProductionNode" and from another interface called "ModelNode" which in turns inherits from the"Node" interface.
When I try to instantiate "ProductionModelNode" compiler claims that the methods defined at "Node" are not implemented, however they are implemented at "ProductionNode".
#include<algorithm>
#include <string>
class Node
{
public:
virtual void clear() = 0;
virtual void append(const std::string&) = 0;
};
class ProductionNode : public Node
{
public:
virtual void clear() override
{
m_name.clear();
}
virtual void append(const std::string& suffix) override
{
m_name += suffix;
}
protected:
std::string m_name;
};
class ModelNode : public Node
{
public:
virtual void reverse() = 0;
virtual void uppercase() = 0;
};
class ProductionModelNode : public ModelNode, public ProductionNode
{
public:
virtual void reverse() override
{
std::reverse(std::begin(m_name), std::end(m_name));
}
virtual void uppercase() override
{
std::transform(m_name.begin(), m_name.end(), m_name.begin(), ::toupper);
}
private:
int m_age;
};
int main(int argc, char** argv)
{
ProductionModelNode mn;
return 0;
}
This is a case of Dreadful Diamond on Derivation.
The class ProductionModelNode has two Node parent, one from ProductionNode is implemented, but the other from ModelNode is not.
Possible "trial" solutions:
Remove the inheritance from ModelNode
Implement clear and append in ProductionModelNode
Use virtual inheritance
Example using virtual inheritance:
class ProductionNode : virtual public Node
...
class ModelNode: virtual public Node
When you define a method with = 0 sign (for example: virtual void reverse() = 0;) it means that the method defined to be Pure virtual.
You must implement every "Pure virtual" method in every class that derive from the class that contains the "pure virtual" methods. (in your case Node class).
class ProductionModelNode : public ModelNode, public ProductionNode
{
public:
...
virtual void clear() override {
//implementation
}
virtual void append(const std::string&) override {
//implementation
}
...
}
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 was very surprised just now to see that this code (paraphrased) built.
class Foo
{
protected:
virtual bool CheckThis(int id);
}
class Bar : public Foo
{
protected:
virtual tErrorCode CheckThis(int id, char something);
};
I thought it was not possible to override a function with a different return type? Somehow this built. OS is vxworks.
In fact, this method:
virtual tErrorCode CheckThis(int id, char something);
Does not override anything, because it has a different signature from this method:
virtual bool CheckThis(int id);
Note, that you might use the override specifier to ensure that the method in the derived class actually overrides the method of the base class.
So, this piece of code:
class Foo {
protected:
virtual bool CheckThis(int id);
};
class Bar : public Foo
{
protected:
virtual tErrorCode CheckThis(int id, char something) override;
};
Will not compile, but this one will:
class Foo {
protected:
virtual bool CheckThis(int id);
};
class Bar : public Foo
{
protected:
virtual bool CheckThis(int id) override;
};
I thought it was not possible to override a function with a different return type?
Yes, it is possible, but with some constraints.
In particular, you can't use any type you want, only a covariant type can be used.
In addition, the argument types must be the same, otherwise it is not an override.
Example:
class type1 {};
class type2 : public type1 {};
class Foo {
protected:
virtual type1& CheckThis(int id);
}
class Bar : public Foo
{
protected:
// This is not an override, it is an overload.
virtual type2& CheckThis(int id, char);
// This is an override.
virtual type2& CheckThis(int id);
};
Since C++11, you should use the special override keyword. It allows the compiler to check if the base class has a method for the derived class to override.
Live example
class Foo
{
protected:
virtual bool CheckThis(int id);
}
class Bar : public Foo
{
protected:
tErrorCode CheckThis(int id, char something) override; // error: marked 'override', but does not override
};
Moreover, since you override a base class method, the virtual keyword is not required in the derived class. The base method is virtual, so the overriding method is implicitly virtual.
When trying to call a method setCurrentState Im getting the error:
StateMachine<Cow>::setCurrentState(std::shared_ptr<State<Cow>>)':
cannot convert argument 1 from 'std::shared_ptr<ChaseState>' to
'std::shared_ptr<State<Cow>>'
This indicates that a std::shared_ptr<ChaseState> is not a std::shared_ptr<State<Cow>> but why is it not?
The call to the function:
std::shared_ptr<ChaseState> initialState = std::make_shared<ChaseState>();
m_stateMachine->setCurrentState(initialState);
State.h
#pragma once
template <class entity_type>
class State
{
public:
virtual void enter(entity_type*) = 0;
virtual void execute(entity_type*) = 0;
virtual void exit(entity_type*) = 0;
};
ChaseState.h
class Cow;
class ChaseState : State<Cow>
{
public:
ChaseState();
// Inherited via State
virtual void enter(Cow*) override;
virtual void execute(Cow*) override;
virtual void exit(Cow*) override;
};
In my StateMachine I have private variable:
std::shared_ptr<State<entity_type>> m_currentState;
and the setCurrentState function:
void setCurrentState(std::shared_ptr<State<entity_type>> s) { m_currentState = s; }
As I understand the derived class ChaseState is a State (behause it inherits from state).
You need to declare your inheritance public. Class inheritance is private by default, meaning that you cannot cast from Derived to Base because the inheritance is not recognized outside of the class itself (same as how private members cannot be accessed outside the class).
To fix, make your inheritance public:
class ChaseState : public State<Cow>
// ^^^^^^
I've created a class named 'Device' which get inherited by multiple devices (for example, RFDevice, AccelleroDevice)
The Device class inherited a Thread class. This Threadclass includes a Pure virtual function named run. Is it possible to accesss this pure virtual function in RFDevice or AcelleroDevice.
So,
ThreadClass->DeviceClass->RFDeviceClass.
I've tried to add
' virtual void run(void) = 0' also in the device class but this wont work.
Greets,
Only if the virtual function is not private. If it is, then you cannot call it and are not supposed to, either:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
private:
virtual void run() = 0;
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
public:
void f()
{
run(); // compiler error
}
};
If it is protected or public, then it will work, provided there is an implementation of the function somewhere down the class hierarchy. But with the exception of the destructor, virtual functions should rarely be public or protected in C++:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
protected:
virtual void run() = 0; // non-private virtual, strange
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
protected:
virtual void run()
{
}
public:
void f()
{
run(); // works
}
};
Of course, this does not technically call the base function. And that's a good thing; you'd end up with a pure virtual function call otherwise, and your program would crash.
Perhaps what you need to do is to just implement the private virtual function. That would be the preferred class design:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
void execute()
{
run();
}
private:
virtual void run() = 0;
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
private:
virtual void run()
{
}
};
int main()
{
RFDevice d;
d.execute();
}
If you are not just maintaining a legacy code base, you should probably get rid of your thread class and use C++11 multi-threading.