I have a C++ inheritance related question. I have a set of classes like this (I have not given the complete class structure coz I am lazy :) ). I want to access chiComponent class public methods using com pointer. How should I go about it?
Note that I am having to change the object which "com" is pointing to in a lot of places.
So I do not think I can have another
chiComponent *ccom = <some_cast> com;
ccom.chiComponentMethod()
How should I go about it?
class Component{
};
class chiComponent : public Component {
public:
void chiComponentMethod()
{
cout << "Hi! Chi component function called!!";
}
}
class parent {
protected:
Component *com;
};
class child : public parent{
public:
child() {
com = new chiComponent();
}
}
Regards
Arun
You will need to implement a pure virtual method in Component; say, componentMethod():
virtual void componentMethod() = 0;
This will make Component an abstract class, and thus uninstantiable.
Then in chiComponent you can have:
virtual void componentMethod() {
chiComponentMethod();
}
Alternatively, you could just rename chiComponentMethod to componentMethod and put the implementation in there directly.
Additionally, any further implementations of Component can implement their own functionality.
Also, I believe that
com = new chiComponent();
should be
*com = new chiComponent();
since com is a Component *.
AVL tree is a type of a BST tree in the sense, that it supports all the BST tree operations and additionally may provide some more. So at the first glance it makes sense to derive AVLTree form the BSTTree. But BSTTree relies on an inner class BSTNode, that is not sufficient for providing all the AVLTree functionality.
If You derive AVLNode from BSTNode there are two options. You could change the BSTNode to support all the functionality the superclass needs, but it doesn't make much sense. It's way better to just design the node class, that supports all the functionality for both types of tries, from the very beginning.
The other option is to make all the BSTTree public methods virtual and explicitly cast the node to AVLNode in all implementations of those methods for the AVLTree class. You want to make those methods virtual anyway. Otherwise if someone is using a BSTTree interface to manipulate an actual instance of an AVLTree (having for example a BSTTree* pointer pointing to an AVLTree instance) disasters are going to happen.
Use virtual functions in the base class:
virtual void chiComponentMethod() = 0;
Easiest way is to make virtual functions in Component and chiComponent, then always use the Component *com base class pointer.
May be I will explain the problem more accurately.
I am trying to code AVL trees in C++ and I am extending AVL class from BST (Binary Search Tree) class. I also have two more classes
class BSTNode {
protected:
int data;
class BSTNode *left, *right;
};
class AVLNode : public BSTNode{
int height;
};
BST class uses BSTNode and AVL class uses AVLNode.
I am using BST class services for things like inorder traversal etc.
For insertion and deletion I am using AVL class functions (through virtual functions).
For obvious reasons I am having a
BSTNode *root in BST class. The root changes whenever I do insert, delete etc.
In AVL class is there any easy way to change **root'**s type to a more specific and more meaningful AVLNode type?
Related
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
Recently, I am learning Inheritance and Polymorphism in C++.
I made three classes: Node, uni_dir_Node(uni-direction Node), and bi_dir_Node(bi-direction Node).
Here is my code:
class Node {
protected:
string name;
Node* next;
virtual void connect(Node* _Node) = 0;
};
class uni_dir_Node : public Node {
void connect(Node* _Node) {
this->next = next;
}
};
class bi_dir_Node : public Node {
Node* previous;
void connect(Node* next_Node, Node* previous_Node) {
this->next = next;
this->previous = previous_Node;
}
};
int main()
{
Node* head = new bi_dir_Node;
return 0;
}
Of course there is a compiler error in this code.
My question is, the function connect() in class uni_dir_Node has one parameter but for the function connect() in class bi_dir_Node has two parameters. How do I keep this inheritance structure and make it legal?
Is there any good way to solve this problem?
As others have said, the problem is that bi_dir_Node doesn't have a void connect(Node* _Node) method.
Conceptually, what's going on is that inheritance indicates an "is a" relationship. Saying that bi_dir_Node inherits from Node means that bi_dir_Node is a Node, so anything that a Node can do, a bi_dir_Node can do.
You're trying to say that bi_dir_Node is a Node but that it can't do everything a Node can: specifically, it can't Connect with a single argument.
The solution is to either provide a single-argument Connect for bi_dir_Node or to remove or redesign the inheritance structure. For example, in C++, templates may be a better approach: you can make uni_dir_Node and bi_dir_Node completely separate (not part of the same inheritance hierarchy) and write template classes and template functions that are generic enough to operate on both.
As says nwp, to have polymorphism, you need to have functions with the same prototypes in the derived classes.
By prototype, it means :
same return type
Same parameter list
const keyword at the end of the prototype must be present on derived if present on base method
same method name of course
This is because all functions need to be called the same way and same semantic whether it is a base or derived object.
virtual key word must be put on the base class method prototype.
The virtual behavior is inherited. So it can be put or not on derived class overriden methods.
Advanced stuff - not often useful :
Since C++ 98 (prehistory !), if a base class method is
Base * Method();
The derived method can be :
Derived * Method();
This is because Derived* IS A KIND of Base*
Hope it clarifies
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.
I have a linked list class (List) that deals only with objects of type Node. It can do all sorts of things with these Nodes assuming that they have boolean comparisons overloaded properly. The thing is, I want to use this List class with a special kind of Node called a Term (an algebraic term with a coefficient and an exponent or degree). How do I tell my List class to use the Term functions (Term has special versions of the Print() function and comparison operators) even though it deals with the Terms using Node pointers? For example, my Print() is something like:
Node* walker=head;
while(walker)
{
walker->Print();
walker=walker->next;
}
Except there is no Node::Print(), I want it to call Term::Print()! Do I have to make a whole new List class to deal with Term class objects?
This is a classic example of Polymorphism. You can add a function Print() to your Node class just like WhozCraig suggested. (Please read up Virtual Functions and Abstract classes in C++.) You can make Print() a virtual function. You can decide whether you want to make Print() a pure virtual function. If it's a pure virtual function, it will be declared like this in the base class.
class Node{
virtual void Print() = 0;
// If you don't want this to be pure virtual
// You can give a generic definition
}
In this case, since you did not define Print() in the base class, each derived class which is not meant to be abstract, must implement this method. Thus, the Term class can derive from Node class and implement it's Print() method accordingly :) And you can use the base class pointer to call this function. If in the future you decide to subclass Node and add a different implementation of Print(), you don't have to change Node at all :)
Hope this helps!
You're already diverging from usual list design - would recommend using templates instead of deriving from Node class. You then would want a foreach method which will do an operation on each node, in this case print. Strongly recommend using the C++ standard library containers instead of coding all this "raw".
Another option (less standard and with design flaws) would be to derive out a PrintList that will call the Print function, and it will need to be templated or to be done in terms of Term nodes as the compiler will expect this function.
Three choices:-
In the real world, you would use std::list or a similar container class
Or, you can add Print() as a virtual method to Node, (and make it abstract, potentially)
class Node {
...
virtual void Print() = 0;
}
Or, you can use cast the Node* to a Term*
Term *t = boost::polymorphic_cast<Term*>(walker);
t->Print();
I was wondering:
With a tree, the root can have multiple children and no id. All nodes (except the root) have an id and the leaf nodes can not have children. It is fixed what type must be used for each depth. So the leaves are always of the same type and so are the parents of the leaves.
Since the root and the nodes can have children and only the nodes have an id I was wondering if the following use of multiple inheritance is acceptable:
class NodeWithId
{
private:
std::string m_id;
};
template<typename T>
class NodeWithChildren
{
private:
std::vector<T> m_nodes;
};
class Network: public NodeWithChildren<Subnet>
{
};
class Subnet: public NodeWithChildren<Machine>,
public NodeWithId
{
};
class Machine: public NodeWithChildren<Application>,
public NodeWithId
{
};
class Application: public NodeWithId
{
};
Or is there a better way to implement this?
edit:
removed virtual
changed classnames
Or is there a better way to implement this?
IMHO, your design creates classes for stuff that are best treated as object instances. At a class level I do not see the need to differentiate between Level1 nodes and Level2 nodes.
Use a design that is simple. Ask yourself, if this design has any potential benefits or not than the naive approach of having a single Node class and creating a tree structure out of Node instances (which you create at runtime).
You could do it with single inheritance:
class NodeWithId
{
private:
std::string m_id;
};
template<typename T>
class NodeWithChildren : public NodeWithId
{
private:
std::vector<T> m_nodes;
};
class Root: public NodeWithChildren<Level1Node>
{
};
class Level1Node: public NodeWithChildren<Level2Node>
{
};
class Level2Node: public NodeWithChildren<LeafNode>
{
};
class LeafNode: public NodeWithId
{
};
You would only need multiple inheritance in the case that you can have a NodeWithChildren that DOESN'T have an ID. In your design above every NodeWithChildren also has a NodeWithId so you may as well derive NodeWithChildren from NodeWithId and totally bypass any potential multiple inheritance problems.
Seems like a "better" design to me ...
First of all, there is no need for virtual inheritance, based on the sample code you posted, there is no 'dreaded diamond'
But I don't really get your design at all, there's no common base class for anything representing your tree, why are you using inheritance at all? It looks like everything could be achieved using composition.
Is this simply a slimmed down version of your hierarchy made for this question?
Your performance will be unbearable, and your code unbelievably convoluted.
First you use a template, which has a vector in it, for each node.
The vector alone will dramatically slow things. Having to cast things would make your traversal code very very slow, and the code itself would be hard to comprehend for anyone else.
Also, since you have different classes, how is the vector able to deal with that? Answer, it can't. That means it has to be a vector of pointers to a base class. Then you have to figure out what the proper type is at runtime to get any use out of them.
If this added some sort of benefit then it might be worth it for some uses, but it's really the opposite of what you want from a structure like a tree, which should be as simple as possible to use and comprehend and have as few memory allocations as possible and ideally good performance.