a class inheritance hierarchy design issue - c++

I have the following class hierarchy for graphs:
typedef vector<int> ArrayI;
typedef vector<Array<long>> Mat2DB;
typedef vector<ArrayI> adjList;
class baseGraph {
int nodes;
ArrayI degree;
//some member functions.
}
class matGraph: public baseGraph {
Mat2DB matrix;
//member functions.
}
class lMatGraph: public matGraph {
ArrayI labels;
//member functions.
}
class listGraph: public baseGraph {
adjList list;
//member functions.
}
class lListGraph: public listGraph {
ArrayI labels;
//member functions.
}
Now in this class I have many other functions, mostly virtual, so that when I get to call the proper function while using the base class pointer.
For example I have a function sssp(int node) which implements single source shortest path. The implementation are both different for class matGraph and class listGraph which are adjacency matrix representation and adjacency list representation of graphs respectively. Now there is not need to change the definition for labelled version of these graphs so I do not define these functions again in lListGraph and lMatGraph
Now the only problem I am havin is with setLabel(const ArratI &) in lListGraph and lMatGraph classes. I need this function to be virtual so that it gets called through base class pointer, but at the same time I do not have anything such as labels for classes matGraph and listGraph.
I do not know if my design hierarchy is correct or not, but it seemed intuitive to me. So any comments on that would be good. What can I do with the setLabel function. Is it okay to have such a function(to me it looks like kind of a workaround so this question) or do I need to reconsider my class hierarchy.
P.S.: I would also love if there are some books from which I can practice design questions like these. I run into these delimma offten and am not sure what to do of them.
EDIT:
Use of class graph is used in another class clustering where I have a member baseGraph *graph i.e.
class clustering {
baseGraph *graph;
}
I am storing the pointer to base class here so that I can use the different algorithms(implemented as functions) from class graph. For clustering class it again depends what type of graph I want to use.

Maybe this ?
typedef vector<int> ArrayI;
typedef vector<Array<long>> Mat2DB;
typedef vector<ArrayI> adjList;
class baseGraph {
int nodes;
ArrayI degree;
virtual void sssp(int node);
//some member functions.
}
class labeledGraph: public virtual baseGraph {
ArrayI labels;
virtual void setLabel(const ArratI &);
//member functions.
}
class matGraph: public virtual baseGraph {
Mat2DB matrix;
//member functions.
}
class lMatGraph: public virtual matGraph, public virtual labeledGraph {
//member functions.
}
class listGraph: public virtual baseGraph {
adjList list;
//member functions.
}
class lListGraph: public virtual listGraph, public virtual labeledGraph {
//member functions.
}
I'm assuming here that you incorrectly inherited from graph when you should have been inheriting from baseGraph (typeo) - though even if not it comes down to same point.
Also rough coding, if you have questions or if there are mistakes feel free to ask.

You say that setLabel should be called through base class pointer, so this necessarily means that it should be declared in the base class, even though it doesn't make sense. You can implement setLabel for graphs that are not labelled in two possible ways:
Do nothing - just ignore the request for setting the labels
Throw an exception (e.g. abort) - something is probably wrong, so the user should know that!
Each way is a workaround, so you should consider why setLabel should be called through base class pointer, and possibly change this decision. I'd expect, if you really need a labelled graph for your algorithm, use the appropriate type instead of a base-class type - then you don't need to do any hacks to the base class.
Note that if you keep adding stuff to the base class that corresponds to each derived class, you are going to end up with a lot of mess in the base class - no good!
In addition, the following may solve your problem with setLabel and make your class hierarchy "healthier".
Consider moving your basic algorithms like sssp away from the class declarations - make them overloaded free-standing functions instead of member functions. This way you won't need to declare sssp in the base class either. If you adopt this guideline, when you implement a new algorithm, the compiler will check all function calls, and issue an error if one is missing (this is better than a crash or getting incorrect results).
class baseGraph {
int nodes;
ArrayI degree;
// a minimum number of member functions (e.g. getNode; getEdges)
}
class matGraph: public graph {
Mat2DB matrix;
}
class lMatGraph: public matGraph {
ArrayI labels;
void setLabel(const ArrayI &);
}
int sssp(const matGraph& graph, int node)
{
// Some code
}
int sssp(const lMatGraph& graph, int node)
{
// Some code; here you can use labels
}
This is discussed in the Effective C++ book (Effective C++ Item 23 Prefer non-member non-friend functions to member functions)

It all boils down to a simple choice. What should happen if I try to set a label in a graph that does not in fact support labels?
Nothing (the attempt may be logged but is otherwise ignored)
A catastrophic failure
I should not be able to even try (the compiler should not let me)
That's it. These are all your options.
The first two options are easy, you just write a virtual function that reports an error (logs it, or throws an exception).
The third one is interesting. It means there is no corresponding virtual function at all. Not in your class and not in any base class. This goes against your design but your design is not necessarily perfect.
So how do you set a label then? Through something that is not a pointer to your base class :) It can be a pointer to another base class (a mixin ― you use multiple inheritance to add labeling functionality to graphs). Or you may templatize your design so that the hierarchy does not really matter and you always statically know the most derived type of your objects.

Related

How to include base class without implementing pure virtual functions? [duplicate]

Having spent quite some time developping in C#, I noticed that if you declare an abstract class for the purpose of using it as an interface you cannot instantiate a vector of this abstract class to store instances of the children classes.
#pragma once
#include <iostream>
#include <vector>
using namespace std;
class IFunnyInterface
{
public:
virtual void IamFunny() = 0;
};
class FunnyImpl: IFunnyInterface
{
public:
virtual void IamFunny()
{
cout << "<INSERT JOKE HERE>";
}
};
class FunnyContainer
{
private:
std::vector <IFunnyInterface> funnyItems;
};
The line declaring the vector of abstract class causes this error in MS VS2005:
error C2259: 'IFunnyInterface' : cannot instantiate abstract class
I see an obvious workaround, which is to replace IFunnyInterface with the following:
class IFunnyInterface
{
public:
virtual void IamFunny()
{
throw new std::exception("not implemented");
}
};
Is this an acceptable workaround C++ wise ?
If not, is there any third party library like boost which could help me to get around this ?
Thank you for reading this !
Anthony
You can't instantiate abstract classes, thus a vector of abstract classes can't work.
You can however use a vector of pointers to abstract classes:
std::vector<IFunnyInterface*> ifVec;
This also allows you to actually use polymorphic behaviour - even if the class wasn't abstract, storing by value would lead to the problem of object slicing.
You can't create a vector of an abstract class type because you cannot create instances of an abstract class, and C++ Standard Library containers like std::vector store values (i.e. instances). If you want to do this, you will have to create a vector of pointers to the abstract class type.
Your workround would not work because virtual functions (which is why you want the abstract class in the first place) only work when called through pointers or references. You cannot create vectors of references either, so this is a second reason why you must use a vector of pointers.
You should realise that C++ and C# have very little in common. If you are intending to learn C++, you should think of it as starting from scratch, and read a good dedicated C++ tutorial such as Accelerated C++ by Koenig and Moo.
In this case we can't use even this code:
std::vector <IFunnyInterface*> funnyItems;
or
std::vector <std::tr1::shared_ptr<IFunnyInterface> > funnyItems;
Because there is no IS A relationship between FunnyImpl and IFunnyInterface and there is no implicit convertion between FUnnyImpl and IFunnyInterface because of private inheritance.
You should update your code as follows:
class IFunnyInterface
{
public:
virtual void IamFunny() = 0;
};
class FunnyImpl: public IFunnyInterface
{
public:
virtual void IamFunny()
{
cout << "<INSERT JOKE HERE>";
}
};
The traditional alternative is to use a vector of pointers, like already noted.
For those who appreciate, Boost comes with a very interesting library: Pointer Containers which is perfectly suited for the task and frees you from the various problems implied by pointers:
lifetime management
double dereferencing of iterators
Note that this is significantly better than a vector of smart pointers, both in terms of performance and interface.
Now, there is a 3rd alternative, which is to change your hierarchy. For better insulation of the user, I have seen a number of times the following pattern used:
class IClass;
class MyClass
{
public:
typedef enum { Var1, Var2 } Type;
explicit MyClass(Type type);
int foo();
int bar();
private:
IClass* m_impl;
};
struct IClass
{
virtual ~IClass();
virtual int foo();
virtual int bar();
};
class MyClass1: public IClass { .. };
class MyClass2: public IClass { .. };
This is quite straightforward, and a variation of the Pimpl idiom enriched by a Strategy pattern.
It works, of course, only in the case where you do not wish to manipulate the "true" objects directly, and involves deep-copy. So it may not be what you wish.
Because to resize a vector you need to use the default constructor and the size of the class, which in turn requires it to be concrete.
You can use a pointer as other suggested.
std::vector will try to allocate memory to contain your type. If your class is purely virtual, the vector cannot know the size of the class it will have to allocate.
I think that with your workaround, you will be able to compile a vector<IFunnyInterface> but you won't be able to manipulate FunnyImpl inside of it. For example if IFunnyInterface (abstract class) is of size 20 (i dont really know) and FunnyImpl is of size 30 because it has more members and code, you will end up trying to fit 30 into your vector of 20
The solution would be to allocate memory on the heap with "new" and store pointers in vector<IFunnyInterface*>
I think that the root cause of this really sad limitation is the fact that constructors can not virtual. Thereof compiler can not generate code which copy the object without knowing its time in the compile time.

Is it alright to put data members in an interface?

Recently, I've learnt about composite pattern. I want to use it in my assignment which I have to implement File and Folder classes. I realize that sub-classes like CFile and Cfolder got to have the same attributes (name and size). So is it alright for me to put the attributes into the interface? As far as I know, it is not good practice to do so. However, I don't understand why I shouldn't. Or is there any other solutions?
I would say its not a problem. Th difference is that instead of a pure interface class you have an abstract base class. However, if you want to retain the flexibility to use the interface for implementations that are not tied down to those specific member variables then you can always create an interface class as well as an abstract base class for full flexibility. Though that may be getting overly complex overly soon, you can always split the interface from the abstract base later if you need to.
using CItemUPtr = std::unique_ptr<class CItem>;
/**
* Interface class
*/
class CItem
{
public:
virtual ~CItem() {}
virtual CItemUPtr findByName(std::string const& name) = 0;
virtual void setHidden(bool a, bool b) = 0;
};
/**
* Abstract base class
*/
class AbstractCItem
: public CItem
{
protected:
std::string name;
std::size_t size;
};
class CFile
: public AbstractCItem
{
public:
CItemUPtr findByName(std::string const& name) override
{
// stuff
return {};
}
void setHidden(bool a, bool b) override {}
};
It's not really a question of "is it a good practice". By creating an interface, you're defining a standard. The question is, do you NEED the implementation of the interface to contain those data members? You are in the best position to understand your implementation, so you're really the only one who can answer this.
As a general rule, the class implementing the interface should be a black box, and the outside world shouldn't have access to any internals (including member data). Interfaces define common functionality that is required to be present to be able to support the interface, and I'd expect those implementation details to be buried in the underlying implementation of the class only, as a general rule. YMMV.
The design principle for a class should be:
'It is impossible to break the class invariant from the outside'
If the constructor(s) set up the class invariant, and all members
uphold the class invariant, this is achieved.
However, if the class does not have a class invariant, having
public members achieves the same thing.
// in C++, this is a perfectly fine, first order class
struct Pos
{
int x,y;
Pos& operator+=(const Pos&);
};
also see https://en.wikipedia.org/wiki/Class_invariant

Inheritance, a parent accesing children in c++

I am making a chess game and when I click on a square I want to know what piece is there. Since there are more than 1 type of pieces it would be annoying to have more variables in the Square structure.
So I have though about a class named Piece which is the parent of each type of Piece.
Example.
class Pawn : public Piece
I want to achieve a Square structure that looks something like this :
struct Square { Piece *piece };
Now, I want to initialize the piece variable like this :
piece = new Pawn(); // or what type of piece it should be.
My problem is that by doing this I can still only access Piece's class functions and not the Pawns ones.
How do I achieve such thing as having only 1 parent which can access everything his children have?
You can make virtual functions.
Define virtual function in base class and override it in child class.
For Example
class Base
{
public:
const char* SayHi() { return "Hi"; } // a normal non-virtual function
virtual const char* GetName() { return "Base"; } // a normal virtual function
virtual int GetValue() = 0; // a pure virtual function
};
class Child:public Base{
{
int GetValue(){
//write any code here
//return something;
}
}
For more refer to link:
http://www.learncpp.com/cpp-tutorial/126-pure-virtual-functions-abstract-base-classes-and-interface-classes/
The best approach by far is try avoiding this situation: can you make the interface of the Piece uniform for all subclasses? If this can be done, choose this design without much hesitation, because what I describe below is a lot more complex, and also much harder to read.
Since you cannot access member functions of derived types through a pointer to the base type, you need to work around this in one of several ways:
Use dynamic_cast<Derived> - This is very simple, but extremely fragile. Changes to the inheritance structure can break an approach based on frequent dynamic casts.
Use VisitorPattern - This is a good choice when the class structure is not expected to change (you're in luck here: the list of types that you plan to model has not changed in many centuries)
Use Runtime Type Information and maps of function objects - This approach is very flexible, but it is somewhat hard to read. Lambdas of C++11 make it easier, though.

Identifying which Base Class shared_ptr has been passed into a Super Class shared_ptr vector

I am working on a C++ project, specifically implementing a shunting yard algorithm.
I have a function that creates a vector of shared_ptr's of type super class, but the classes that are being pushed into this vector are all base class shared_ptrs.
I then need to take this vector and pass it into another function and carry out different logic for each element of the vector in a for loop. The logic that I carry out, however, depends on which base class is present in each element of the vector.
So basically what I don't know is how to identify which type of base class is in each element of the vector. When I debug they are all coming out as type super-class.
So generally I'd like to do something like this:
if(vectorElement == baseClass)
{
//do some logic
}
Or if there is some different method of carrying this out which I'm missing I'd be interested in carrying that out.
There are many solutions to your problem, frankly is the almost most common problem in OOP.
The most obvious is the virtual function doing different things in different classes:
class SuperClass {
public:
virtual void doSomething(/*someArgsIfNeeded*/) {
// some base implementation, possible empty
// or just use pure virtual function here
}
};
class SubClass : public SuperClass {
public:
virtual void doSomething(/*someArgsIfNeeded*/) {
// some base implementation
}
};
Then use it as follows:
int SomeArgs;
std::vector<std::shared_ptr<SuperClass>> objects;
for (auto it = objects.begin(); it != objects.end(); ++i)
it->doSomething(/*someArgsIfNeeded*/);
Other more sophisticated solution is to use visitor pattern.
It is considered a bad practice to use casting (dynamic_cast), so always search for more OO solutions than casting, like these two I presented above.
Off the top of my head, a simple solution would be to have a function in the base class, that returns an int signifying which class it is. And in each of the derived classes, override this function to return different values. You could use that value to determine which class is being stored in the vector
Edit: And Generally class specific details are to be left in the class, which is the point of polymorphism. Try to do the derived class specific calculations as an overided member function within each class, and use that just to fetch the value forgoing the need for large for loops (for each new derived class) outside.

correct Inheritance/class structure

i want to write a library for linear program solving. Thereby several solvers such as cplex or gurobi are used. What i already have is an interface for each of them (all containing the same functions wrapping them to solver specific code).
Now I want to have a class 'LinearProgram' which can be instantiated e.g. by LinearProgram("cplex") which then invokes the cplex solver.
My first idea was to use a super class 'solver' which is a base class of all solver interfaces containing the respective functions as virtual declarations. But then I get an abstract class which can not be instantiated.
So in LinearProgram i wanted to have a variable Solver which is instantiated depending on the string given in the constructor.
I'm sure a proper solution is quite obvious, but all I can think about in the moment is not satisfying.
Thanks for your help.
This illustrates what you describe:
class Solver {
...abstract base
};
class SolverFactory {
public:
Solver* NewSolverWithName(const std::string& pSolverName);
};
class LinearProgram {
public:
LinearProgram(const std::string& pSolverName) :
d_solver(SolverFactory::NewSolverWithName(pSolverName)) {
}
private:
some_auto_pointer<Solver> d_solver;
};
class cplex_Solver : public Solver {
...
static std::string Name();
};
Solver* SolverFactory::NewSolverWithName(const std::string& pSolverName) {
if (pSolverName == cplex_Solver::Name()) {
return new cplex_Solver();
}
...
}
This is a job for two different design patterns combined.
The first is the Envelope Letter pattern, and the second is the Strategy Pattern.
Keep on with the base class that you currently have and make a derived class that simply forwards the call to an embedded pointer to the base class. The derived class is now something you can freely pass around by value.
The base class could also contain a static member function that returns a pointer to the base class. This static member function would allow you to instantiate a derived class by using a string name to look it up. That provides a convenient way to select an algorithm at runtime.
But people who knew which derived class (which strategy) they wanted could just create one with 'new' and stuff it inside an instance of the envelope class.
You can optionally do away with the envelope class if you decide to just use a shared_ptr to the base class instead.