Create virtual function with unknown number of parameters - c++

I am looking to have a virtual class used to ensure that all inheriting classes have the following functions
Initialize()
IsInitialized()
Clear()
Maybe there is another approach but the use of the abstract class seems to be the best options as far as I can tell.
The issue is that the Initialize() does not always have the same parameters For example:
class baseObject
{
virtual void Initialize(...) = 0; //Only want to ensure Initialize is implemented in the inheriting class but parameters may very
virtual void Clear() = 0;
virtual bool IsInitialized() = 0;
}
class triangle : public baseObject
{
virtual void Initialize(double length1, double length2, double length3); //Three parameters
virtual void Clear();
vitrual bool IsInitialized();
...
}
class square : public baseObject
{
virtual void Initialize(double baseLength, double baseHeight); //two parameters
virtual void Clear();
virtual bool IsInitialized();
...
}
etc...

Related

How can i define a pure abstract base class

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!

Extract implementer when inheritance hierarchy in C++

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
}
...
}

Using a "superclass" object to handle inherited classes

I am making a program that solves a number of similar problems.
I am starting with a class that looks like (for example):
class problem {
void init();
void solve();
int print_result();
}
but then I would like to extend this class to different problems:
class problem_A : problem {
void init();
void solve();
void print_result();
}
class problem_B : problem {
void init();
void solve();
void print_result();
}
...
But in the main interface I would like to have a single object for either of the problems (A, B, ...) and handle them like:
obj.init();
obj.solve();
obj.print_result();
How do I achieve this? What type should obj be?
If you always want to call init() then solve() then print_result(), it's best to wrap this up in the (for C++) awkwardly named Template Method Pattern:
class problem {
public:
virtual ~problem() = default;
void run() {
init();
solve();
print_result();
}
protected:
virtual void init() = 0;
virtual void solve() = 0;
virtual void print_result() = 0;
};
And then each of your explicit problems just have to provide implementations for those functions:
class problem_A : public problem {
protected:
void init() override { .. }
void solve() override { .. }
void print_result() override { .. }
};
problem* p = new problem_A(..);
p->run(); // inits, solves, and prints the results for problem A
You stick with your original class, but make the methods pure virtual
class problem {
virtual void init() = 0;
virtual void solve() = 0;
virtual int print_result() = 0;
}
Then you can override these functions in the derived classes
class problem_A : problem {
virtual void init() override;
virtual void solve() override;
virtual void print_result() override;
}
Then you can make your object as follows:
problem* obj = new problem_A;
obj->init();
obj->solve();
obj->print_result();
This will invoke problem_A's methods, but you can use a pointer to the base class problem. Obviously make sure you clean up the memory
delete obj;
Or use smart pointers
std::unique_ptr<problem> = std::unique_ptr<problem>(new problem_A);

Best way to work with an abstract class member in an abstract base class?

I'm not happy with the question title, but I couldn't describe it well. I'm putting implementation in the class declarations for sake of brevity.
I have a class like this:
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<sf::Shape> shape;
}
sf::Shape is an abstract class. Then I have a derived class like so:
class Brick : VisibleObject {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
std::dynamic_pointer_cast<sf::RectangleShape>(shapes).get()->setSize(newSize);
}
}
sf::RectangleShape() is a concrete class that inherits from sf::Shape and setSize() is defined for it, not sf::Shape, which is why I need to cast.
Of course, I need to do some error handling, in the case that the dynamic cast fails and returns an empty shared_ptr.
I'm doing this because I wanted to be able to define the draw method just once, since in this simple game, every object will draw their member this way. Originally I left the shape out of the base class, and e.g. Brick would just have its own private sf::RectangleShape that could get instantiated on the stack; which was clean, but then the draw method had to be re-written for each object type.
This works, but is uglier to work with and introduces heap allocation. I also have shared_ptr overhead (I would have used unique_ptr, but I needed dynamic casting).
Is this the most appropriate way of doing what I'm trying to do?
It might be preferable to keep the interface an interface, and not start mandating implementation details. So just have an empty base class like so:
class VisibleObject
{
public:
~VisibleObject() {}
virtual void draw(sf::RenderWindow & window) = 0;
virtual void setSize(sf::Vector2f const & size) = 0;
};
You can stick the shape storage into the concrete class that implements this interface.
Moreover, Shape should provide a virtual resize method:
class Shape
{
public:
virtual ~Shape() {}
virtual void resize(sf::Vector2f const & size) = 0;
};
Now you can make, say, a VisibleShapeObject as an intermediate base class:
class VisibleShapeObject : public VisibleObject
{
public:
virtual void draw(sf::RenderWindow & window) override final
{
window.draw(*shape_);
}
virtual void setSize(sf::Vector2f const & size) override final
{
shape_->resize(size);
}
protected:
std::shared_ptr<Shape> shape_; // or unique_ptr<Shape>
};
Instead of mandating storage in std::shared_ptr<sf::Shape>, why not simply introduce a means of retrieving an sf::Shape& from the concrete class?
class VisibleObject {
virtual sf::Shape& getShape() = 0;
public:
void draw(sf::RenderWindow& rw) {
rw.draw(getShape());
}
virtual void setSize(sf::Vector2f) = 0;
};
class Brick : VisibleObject {
sf::RectangleShape shape;
sf::Shape& getShape() override { return shape; }
public:
void setSize(sf::Vector2f newSize) override {
shape.setSize(newSize);
}
};
It seems ridiculous to store via a pointer to base, introducing indirections and downcasts and reference count overhead, when you could just store a plain old member. In fact, if I'm understanding the problem correctly, you could probably use a template to generate concrete classes and avoid a lot of boilerplate:
class VisibleObject {
public:
virtual ~VisibleObject() {}
virtual void draw(sf::RenderWindow&) = 0;
virtual void setSize(sf::Vector2f) = 0;
};
template <typename Shape>
class VisibleConcreteObject : public VisibleObject {
Shape shape;
public:
void draw(sf::RenderWindow& rw) override /* final? */ {
rw.draw(shape);
}
void setSize(sf::Vector2f newSize) override /* final? */ {
shape.setSize(newSize);
}
};
typedef VisibleConcreteObject<sf::RectangleShape> Brick;
You haven't shared everything you are trying to do, but this it one way:
template<ShapeT>
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<ShapeT> shape;
void reset(ShapeT* shape) {
this->shape = shape;
}
}
class Brick : VisibleObject<sf::RectangleShape> {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
shape->setSize(newSize);
}
}
There may be reasons why this doesn't work for you, but without more insight, I couldn't guess at what.

Design Pattern: uniform interface for partially supported derived classes

I am designing an interface for my project and curious if the idea can come true or not.
Here is the situation,
At run time, I want to use an array of base class pointers to issue commands to different derived objects. Different derived objects got different implementation (virtual functions). My problem is: if those objects got different different support level of the interface, how can I avoid writing an empty function?
For example, (my current code)
Class Base { //this is the main interface
public:
virtual void basicFun() = 0;
virtual void funA(int input1) {return;}
virtual void funB(int input2) {return;}
virtual void funC(int input3) {return;}
}
Class Derived1 : public Base { //this class support only funA()
public:
void basicFun() {//....}
void funA(int input1) {//do something}
}
Class Derived2 : public Base { //this class support both funA() funB()
public:
void basicFun() {//....}
void funA(int input1) {//do something}
void funB(int input2) {//do something}
}
Class Derived3 : public Base { //this class support all
public:
void basicFun() {//....}
void funA(int input1) {//do something}
void funB(int input2) {//do something}
void funC(int input3) {//do something}
}
Assumption: for a certain object, unsupported function would never be called. i.e. BasePtr->funC() will never be called if the object pointed by basePtr is Derived1 or Derived2.
The problem is:
I must define an empty function either in Base or Derived if an uniform interface is desired
If empty functions are defined like above, compiler keeps warning me unreferenced parameters (input1~input3). Of course I can turn it off, but just don't like this way.
So, is there any pattern that I can use to achieve an uniform interface without defining empty functions? I have been thinking about this for a few days. It seems impossible. Because funA() funB() and funC() must be in the interface so that I can use a Base pointer array to control all objects, which means in Derived1, funB() and funC() must somehow be defined.
Thanks, and happy thanksgiving, and thanks for sharing your ideas.
Solti
Uniform interfaces are a good thing. Which means that you must implement all methods in an interface, even if it means you will have empty methods. There is no design pattern for this problem, because it's not a real problem in the first place.
Think about this for a moment: say you have a Car interface, with methods Accelerate() and Brake(). A class that derives from Car must implement all methods. Would you want an object derived from Car implement the Accelerate() method but not the Brake() method? It would be an amazingly unsafe Car!
An interface in the context of OOP must have a well defined contract that is adhered to by both sides. In C++, this is enforced to a certain extent by requiring all pure virtuals to be implemented in derived class(es). Trying to instantiate a class with unimplemented virtual methods result in compilation error(s), assuming one doesn't use stupid tricks to get around it.
You object to creating empty methods because they cause compiler warnings. In your case, just omit the parameter name:
void funC(int) // Note lack of parameter name
{
}
Or comment the name out:
void funC(int /*input3*/)
{
}
Or even by using templates!
template<class T> void ignore( const T& ) { }
//...
void funC(int input3)
{
ignore(input3);
}
Here's what I would have done: create a helper base class with empty default implementations of all pure virtual methods. Then you can derive from this base class instead of the main interface and then select which method to override.
// main interface, everything pure virtual
struct IBase
{
virtual ~IBase() {}
virtual void basicFun() = 0;
virtual void funA(int input1) = 0;
virtual void funB(int input2) = 0;
virtual void funC(int input3) = 0;
};
// helper base class with default implementations (empty)
class Base : public IBase
{
void basicFun() {}
void funA(int input1) {}
void funB(int input2) {}
void funC(int input3) {}
};
class Derived1 : public Base { //this class support only funA()
void funA(int input1) {//do something}
};
class Derived2 : public Base { //this class support both funA() funB()
void funA(int input1) {//do something}
void funB(int input2) {//do something}
};
class Derived3 : public IBase { //this class support all
void basicFun() {//....}
void funA(int input1) {//do something}
void funB(int input2) {//do something}
void funC(int input3) {//do something}
};
int main()
{
// I always program to the interface
IBase& b1 = Derived1(); b1.basicFun(); b1.funA(); b1.funB(); b1.funC();
IBase& b2 = Derived2(); b2.basicFun(); b2.funA(); b2.funB(); b2.funC();
IBase& b3 = Derived3(); b3.basicFun(); b3.funA(); b3.funB(); b3.funC();
}
If you truly need non uniform interfaces (think about it before), maybe the Visitor pattern is worth a try:
struct Visitor;
struct Base
{
virtual ~Base() {}
virtual void accept(Visitor& v) { v.visit(*this); }
};
struct InterfaceA : Base
{
void accept(Visitor& v) { v.visit(*this); }
virtual void MethodA() = 0;
};
struct InterfaceB : Base
{
void accept(Visitor& v) { v.visit(*this); }
virtual void MethodB() = 0;
};
struct InterfaceA2 : InterfaceA
{
void accept(Visitor& v) { v.visit(*this); }
void MethodA(); // Override, eg. in terms of MethodC
virtual void MethodC() = 0;
};
// Provide sensible default behavior. Note that the visitor class must be
// aware of the whole hierarchy of interfaces
struct Visitor
{
virtual ~Visitor() {}
virtual void visit(Base& b) { throw "not implemented"; }
virtual void visit(InterfaceA& x) { this->visit(static_cast<Base&>(x)); }
virtual void visit(InterfaceA2& x) { this->visit(static_cast<InterfaceA&>(x)); }
virtual void visit(InterfaceB& x) { this->visit(static_cast<Base&>(x)); }
};
// Concrete visitor: you don't have to override all the functions. The unimplemented
// ones will default to what you expect.
struct MyAction : Visitor
{
void visit(InterfaceA& x)
{
x.MethodA();
}
void visit(InterfaceB& x)
{
x.methodB();
}
};
usage:
Base* x = getSomeConcreteObject();
MyAction f;
x->accept(f);
this will invoke either MethodA or MethodB depending on the runtime type of x. The visitor as implemented allows you not to overload many functions, and falls back to the action for a base class if the behavior is not implemented. Eventually, if you fail to provide an action in a visitor for some class, it will default to throw "not implemented".
Const correctness may force you to distinguish between Visitor and ConstVisitor, for whom all the accept methods would be const.