this is my situation:
I am writing a data structure in C++ which consists of Nodes and Edges.
Nodes are connected to other nodes by means of edges.
I have different types of nodes, such as text nodes, or int nodes.
Text nodes are connected to text nodes and int nodes are connected to int nodes.
I am using inheritance to implement the different types of nodes because it makes sense:
fundamentally, all nodes are connected to other nodes so Node is the base class,
and TxtNode, IntNode are inherited classes which share the fundamental property of a node.
However, this gives me problems when I try to fetch a connected inherited node from an inherited node, because the fetching function (function which retrieves a specific node connected to the calling node) is defined in the base class Node. For example, calling this fetch function from TextNode returns me the base version of the TextNode, which lacks extra information.
I am not sure what would be the sensible coding practice to do here.
I chose to code it this way because it didn't seem to make sense that I must define a different connection fetch function for all different types of nodes.
Please let me know if there is any more information I can disclose.
Here is my code, I am trying to print an inherited node's partner but it will result in printing the base node.
Node.cpp
#include "Node.h"
#include "Edge.h"
#include "common.h"
#include <vector>
#include <cassert>
#include <cstddef>
#include <stdint.h>
#include <iostream>
Node::Node() {
id = (intptr_t)this;
edges.clear();
}
int Node::connect(Node* dst) {
// establish link between calling node
// and dst node, first linkage will
// edge between each other, links after
// increments strength. returns number of
// links
// fetch edge connecting this node and
// dst node
Edge* edge = findDstEdge(dst);
// if the branch isn't established yet,
// then make connection
if (edge==NULL) {
establishConnection(dst, 1);
return 0;
} else {
edge->strengthenConnection();
return 1;
}
}
Edge* Node::findDstEdge(Node* dst) {
// fetches edge corresponding
// to destination node
// walk through vector of edges to find
// edge connecting to dst
vector<Edge*>::iterator iter = edges.begin();
while(iter!=edges.end()) {
Edge* e = *iter;
Node* partner = e->getPartner(this);
if (partner->getID() == dst->getID())
return e;
iter++;
}
// not found
return NULL;
}
void Node::establishConnection(Node* dst, int str) {
// low level node addition
// establish a new edge between
// nodes which don't know each other
Edge* e = new Edge(this, dst, str);
this->manuallyConnect(e);
dst->manuallyConnect(e);
}
void Node::manuallyConnect(Edge* e) {
edges.push_back(e);
}
ostream& operator<<(ostream& stream,Node n) {
vector<Edge*>::iterator iter = n.edges.begin();
while(iter!=n.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include "common.h"
#include <vector>
#include <string>
#include <stdint.h>
class Edge;
using namespace std;
class Node {
protected:
vector<Edge*> edges;
intptr_t id;
public:
Node();
// manipulation
void establishConnection(Node* dst,
int str);
int connect(Node* dst);
Edge* findDstEdge(Node* dst);
// fetchers
intptr_t getID() {return id;}
vector<Edge*> getEdges() {return edges;}
void manuallyConnect(Edge* e);
friend ostream& operator<<(ostream& stream, Node n);
};
#endif
TxtNode.cpp
#include "TxtNode.h"
#include "Edge.h"
#include "common.h"
#include <iostream>
TxtNode::TxtNode(char c): Node() {
_c = c;
}
ostream& operator<<(ostream& stream, TxtNode tn) {
// print out character of this TxtNode
stream << "char: " << tn._c << endl;
stream << "id: " << tn.id << endl;
// print out all connections and its
// strength
vector<Edge*>::iterator iter = tn.edges.begin();
while(iter!=tn.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Edge.cpp
#include "Edge.h"
#include "Node.h"
#include "common.h"
#include <cassert>
#include <iostream>
using namespace std;
Edge::Edge(Node* a, Node* b, int str) {
node_a = a;
node_b = b;
strength = str;
}
void Edge::strengthenConnection() {
strength++;
}
Node* Edge::getPartner(Node* src) {
uint src_ID = src->getID();
if (node_a->getID() == src_ID)
return node_b;
else if (node_b->getID() == src_ID)
return node_a;
assert(false);
}
ostream& operator<<(ostream& stream, Edge e) {
stream << "strength: "
<< e.strength
<< endl;
stream << "node_a: "
<< e.node_a->getID()
<< endl;
stream << "node_b: "
<< e.node_b->getID()
<< endl;
return stream;
}
Currently I just have the code to print the ID which is an intptr_t,
because I found out that I can't access inherited class's member from base class.
I am inclined to access the inherited class's member from base class because the edge class deals with base node class.
The classes code would've been a nice to have.
From what you are telling you don't declare the fetch function virtual.
Here's a very quick example on how virtual / non virtual functions work
class baseNode {
public:
int fetch() { printf "fetched from base";};
}
class intNode : public baseNode {
public:
int fetch() { printf "fetched from derived int";};
}
class txtNode : public baseNode {
public:
int fetch() { printf "fetched from derived txt";};
}
The following code
baseNode * ptr = new intNode();
ptr->fetch();
Will print "fetched from base"
But if you declare the fetch function virtual :
class baseNode {
public:
virtual int fetch() { printf " fetched from base";};
}
Then the same code will print "fetched from derived int".
You write
“ Text nodes are connected to text nodes and int nodes are connected to int nodes.
Then you can very simply define Node_ as a class template:
template< class Value >
struct Node_
{
vector<Node_*> connected_nodes;
Value value;
};
In other words, use compile time polymorphism, not dynamic polymorphism, in order to have the relevant type information available at compile time.
That said, do have a look at Boost.Graph and see if it doesn't suit your needs.
Related
y'all I'm having an issue trying to access the member functions of an object that I have stored in an array of pointers full of objects.
Header:
#ifndef COURSEGRADES__H
#define COURSEGRADES__H
#include "Essay.h"
#include "FinalExam.h"
#include "PassFailExam.h"
#include "GradedActivity.h"
class CourseGrades:public Essay, public FinalExam, public PassFailExam, public GradedActivity
{
public:
CourseGrades();
void setLab(GradedActivity &l);
void setPassFailExam(PassFailExam &pf);
void setEssay(Essay &e);
void setPassFailFinal(FinalExam &fe);
void print();
private:
GradedActivity *grades[4];
};
#endif // COURSEGRADES_H
CPP
#include "CourseGrades.h"
#include <iostream>
CourseGrades::CourseGrades()
{
//ctor
}
void CourseGrades::setLab(GradedActivity &l)
{
grades[0] = &l;
}
void CourseGrades::setPassFailExam(PassFailExam &pf)
{
grades[1] = &pf;
}
void CourseGrades::setEssay(Essay &e)
{
grades[2] = &e;
}
void CourseGrades::setPassFailFinal(FinalExam &fe)
{
grades[3] = &fe;
}
void CourseGrades::print()
{
std::cout << grades[0]->getScore() << "\t" << grades[0]->getLetterGrade() << std::endl;
std::cout << grades[1]->getScore() << "\t" << grades[1]->getLetterGrade() << std::endl;
std::cout << grades[2]->getScore //this function exists in the Essay class but I can't access it from here.
}
So I'm trying to access the third object in the grade array which is an object of the essay class which includes a unique function that is separate from the get score function in the GradeActivity class. I'll also need to access its unique getLetterGrade method but once I get one I should be able to find out how to get the other. Any help would be greatly appreciated.
#include "dataConsumer.h"
#include <iostream>
#include <Windows.h>
DataConsumer::DataConsumer(){}
DataConsumer::~DataConsumer(){}
void DataConsumer::Body()
{
std::cout << "DataConsumer Start" << std::endl;
while (1)
{
//I want to get providerData_ of DataProvide class in here
Sleep(1000);
}
}
#include "dataProvider.h"
#include <iostream>
#include <Windows.h>
DataProvider::DataProvider(){}
DataProvider::~DataProvider(){}
void DataProvider::Body()
{
std::cout << "DataProvider Start" << std::endl;
while (1)
{
//Update data in here
providerData_++;
Sleep(1000);
}
}
There are two classes.
And I want to get providerData_ of dataProvider class in dataConsumer class.
To resolve this situation, I thought the following is one solution.
I made singleton dataTransfer class like below.
But I am not sure whether this is a general solution in c++.
First of all, I want to know whether my solution is available.
To the next, If you know the better solution(or design pattern) to resolve my situation, please advise to me.
#ifndef DATATRANSFER_H
#define DATATRANSFER_H
class DataTransfer
{
public:
static DataTransfer* getInstance()
{
static DataTransfer instance;
return &instance;
}
void GetData(unsigned int *data)
{
if(data)
*data = data_;
}
void SetData(unsigned int *data)
{
if(data)
data_ = *data;
}
private:
DataTransfer(){}
~DataTransfer(){}
unsigned int data_;
};
#endif
#include "dataConsumer.h"
#include "dataTransfer.h"
#include
#include
DataConsumer::DataConsumer(){}
DataConsumer::~DataConsumer(){}
void DataConsumer::Body()
{
unsigned int data = 0;
std::cout << "DataConsumer Start" << std::endl;
while (1)
{
//I want to get providerData_ of DataProvide class in here
DataTransfer::getInstance()->GetData(&data);
std::cout << "DataConsumer data:" << data << std::endl;
Sleep(1000);
}
}
#include "dataProvider.h"
#include "dataTransfer.h"
#include
#include
DataProvider::DataProvider() : providerData_(0)
{
}
DataProvider::~DataProvider(){}
void DataProvider::Body()
{
std::cout << "DataProvider Start" << std::endl;
while (1)
{
//Update data in here
providerData_++;
DataTransfer::getInstance()->SetData(&providerData_);
Sleep(1000);
}
}
If both classes need to be able to get and set the providerData_, I would create a third Data class to own the providerData_.
Then I could give a pointer of the Data class to all the classes that needed access to that data.
There are 3 patterns called aggregation, composition and association in software architecture.
The pattern in which class Foo can use class Bar but does not "own" it and both classes remain independent is Association.
DataConsumer have a pointer to DataProvider :
// Association
class DataConsumer{
private:
DataProvider* provider;
public:
void setProvider(DataProvider* p) { provider = p; }
void Body();
int /* or whatever data type */ getData()
{
if(provider != nullptr)
{
return provider->getData();
}
else
{
// handle provider not being set
return ...;
}
}
};
DataProvider must be allocated / created outside of DataConsumer and is independent.
Read this answer and this answer for a better explanation on these pattern.
I have a class Branch and a class Tree. The declaration of the classes looks like:
class Branch{
private:
map<string, double> properties;
vector<Branch *> parent;
vector<Branch *> children;
int hierarchy;
public:
...
}
class Tree{
private:
/* Tree is a vector of pointers to branches. */
vector<Branch*> tree_branches;
map<int,int> Hierarchy_distribution;
public:
...
}
1) If I understood well, the fact that the only attributes of Tree class are a vector and a map, makes it unnecessary to declare a destructor, a copy-assignement operator and a copy constructor, because the memory is managed "inside" the vector and map templates.
2) I use this classes from a python code (I used cython to interface between C++ an python) and all the operations I make are performed through a tree object. I thought that because the branches I "use" are contained in a tree object (with a good memory management) I didn't need to declare a destructor, a copy constructor,and a copy assignment operator for the branch class. However I'm experiencing some problems and I think I have a memory leak.
Can someone confirm me if this could be causing a memory leak? If it is would stocking the int hierarchy inside a vector<int> avoid declaring a destructor and company?
EDIT
The branches who are stocked in the tree are created inside a method of the Tree class. It looks like:
Tree::addBranch(){
Branch* branch2insert=new Branch();
tree_branches.push_back(branch2insert);
}
As a local variable, is branch2insert destructed at the end of the scope? Do I need to write delete branch2insert;? Does someone have an idea of where do the Branch object at which I point to lives?
I still don't get why I need to ensure memory management when I never allocate ressources except inside the Tree class methods...
This whole thing is getting very messy in my head
EDIT 2:EXAMPLE
branch.h
#ifndef BRANCH_H_
#define BRANCH_H_
#include <memory>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Branch{
private:
vector<Branch*> parent;
vector<Branch*> children;
public:
Branch();
bool hasParent();
bool hasParent(Branch* test);
void addParent(Branch* p);
void removeParent();
Branch* getParent();
bool hasChildren();
bool hasChild(Branch*test);
void addChild(Branch*ch);
void removeChild(Branch*ch);
void removeChildren();
void removeDescendants();
vector<Branch*> getBrothers();
};
#endif
tree.h
#ifndef TREE_H_
#define TREE_H_
#include <vector>
#include <map>
#include"branch.h"
using namespace std;
class Tree{
private:
vector<Branch*> tree_branches;
public:
Tree();
int getNumberOfBranches();
Branch* getBranch(int branch_index); /* Returns branch at index. */
int getIndex(Branch* branch); /* Returns the index of branch. */
int getLastDescendantIndex(int ancestor_index); /* Returns index of the last descendant of branch at ancestor index. */
int getParentIndex(int child_index); /* Returns index of the parent of branch at child_index. */
vector<int> getBrothersIndex(int branch_index); /* Returns indexes of the brothers of branch at branch_index. */
void addBranch(int parent_index); /* Adds branch without initializing its properties. */
void removeBranch(int branch_index); /* Removes branch at branch_index and all its descendants. */
};
#endif
branch.cpp
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <sstream>
#include <map>
#include <stdio.h>
using namespace std;
#include "branch.h"
Branch::Branch():parent(vector<Branch*>()),children(vector<Branch*>())
{
}
bool Branch::hasParent(){
if(parent.size()==0)
return false;
else
return true;
}
bool Branch::hasParent(Branch* test){
bool ret = false;
for(vector<Branch*>::iterator it=parent.begin();it!=parent.end();it++){//traversing parent vector
if((*it)==test){//if test belong to parent vector
ret = true;
break;
}
}
return ret;
}
void Branch::addParent(Branch* mom){
if(parent.size()==0){//if a branch hasn't a parent, multiple parents aren't allowed in a tree-network
if(hasParent(mom)==false){//double checking if mom isn't already a parent
parent.push_back(mom);//adding mom to parent vector
}
else{
cout << "Branch::addParent Error: trying to add a parent twice.\n";
}
}
else{
cout << "Branch::addParent Error: trying to add a parent to a branch that already has one.\n";
}
}
void Branch::removeParent(){
if(this->hasParent()==true){//if this branch has a parent
vector<Branch*>::iterator it=parent.begin();
parent.erase(it);//erase it (it is the first and only element of the vector)
}
else{
cout << "Removing the trunk.\n";
}
}
Branch* Branch::getParent(){
return parent[0];
}
bool Branch::hasChildren(){
if(children.size()==0)
return false;
else
return true;
}
bool Branch::hasChild(Branch* test){
bool ret = false;
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
if((*it)==test){
ret = true;
break;
}
}
return ret;
}
void Branch::addChild(Branch* ch){
if(hasChild(ch)==false){
children.push_back(ch);
ch->addParent(this); // PARENTHOOD LINK ESTABLISHED IN ADD CHILD. ONLY
// NEEDED ONCE.
}
else{
cout << "Branch::addChild Error: trying to add a child but the child has been already added.\n";
}
}
void Branch::removeChild(Branch* ch){
if(hasChild(ch)==true){
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
if((*it)==ch){
children.erase(it);
break;
}
}
}
else{
cout << "Branch::removeChild Error: trying to remove a child that doesn't exist.\n";
}
}
void Branch::removeChildren(){
if(this->hasChildren()==true){
children.erase(children.begin(),children.end());
}
else{
cout << "Branch::removeChildren Error: trying to remove all the children of a branch but tha branch hasn't any.\n";
}
}
void Branch::removeDescendants(){
if (this!=NULL){
if(this->hasChildren()==true){
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
(*it)->removeDescendants();
}
removeChildren();
}
for(vector<Branch*>::iterator it=children.begin();it!=children.end();it++){
(*it)->removeParent();
}
}
}
vector<Branch*> Branch::getBrothers(){
vector<Branch*> brothers;
vector<Branch*> potential_brothers;
if (parent.size()!=0){
potential_brothers=parent[0]->children;
for (vector<Branch*>::iterator it=potential_brothers.begin();it!=potential_brothers.end();it++){
if ((*it)!=this){
brothers.push_back((*it));
}
}
}
return brothers;
}
tree.cpp
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#include "tree.h"
Tree::Tree():tree_branches(vector<Branch*>()){
Branch* trunk=new Branch();
tree_branches.push_back(trunk);
}
int Tree::getNumberOfBranches(){
int number_of_branches=tree_branches.size(); //retrieving size of vector
return number_of_branches;
}
Branch* Tree::getBranch(int index){
unsigned int u_index=index;
return tree_branches.at(u_index); // returning branch at index of the tree vector
}
int Tree::getIndex(Branch* branch){
int index=0;
for(vector<Branch*>::iterator it=tree_branches.begin();it!=tree_branches.end();it++){
if((*it)==branch){
return index;
}
index++;
}
cout << "Tree::getIndex Error: trying to get the index of a branch we can't find. Returning 0.\n";
return 0;
}
int Tree::getLastDescendantIndex(int ancestor_index){
if(tree_branches.at(ancestor_index)->hasChildren()==false){// if it is a leaf
return ancestor_index;
}
if(ancestor_index==0){// if it is the trunk
int N=tree_branches.size();
int last_descendant_index=N-1;
return last_descendant_index;
}
vector<int> brothers_indexes=Tree::getBrothersIndex(ancestor_index);
for(vector<int>::iterator it=brothers_indexes.begin();it!=brothers_indexes.end();it++){
int brother_index=(*it);
if(brother_index>ancestor_index){
int last_descendant_index=brother_index-1;
cout << "The last descendant of" << ancestor_index << " is "<<last_descendant_index<<"\n";
return last_descendant_index;
}
}
int parent_index=Tree::getParentIndex(ancestor_index);
Tree::getLastDescendantIndex(parent_index);
}
int Tree::getParentIndex(int child_index){
if(child_index==0){ //if considered branch is the trunk
cout << "Tree::getParentIndex: the trunk hasn't a parent. Returning -1.\n";
return -1;
}
unsigned int u_child_index=child_index;
Branch* parent=tree_branches.at(u_child_index)->getParent(); //retrieving the parent of the considered branch
int parent_index=Tree::getIndex(parent);
return parent_index; //returning parent index
}
vector<int> Tree::getBrothersIndex(int branch_index){
vector<int> brothers_index;
Branch* this_branch=Tree::getBranch(branch_index);//retrieving the branch from the index
vector<Branch*> brothers=this_branch->getBrothers();//retrieving branch's brothers
for(vector<Branch*>::iterator it=brothers.begin();it!=brothers.end();it++){ //traversing a vector containing the brothers of the consideered branch
int this_index=Tree::getIndex(*it); //retrieving index of a brother
brothers_index.push_back(this_index); //stocking the index in a vector
}
return brothers_index; //returning the vector containing the index of all brothers
}
void Tree::addBranch(int parent_index){
unsigned int u_parent_index=parent_index;
Branch* mom=tree_branches.at(u_parent_index);//getting futur parent
Branch* branch2insert=new Branch();//creation of branch to insert
mom->addChild(branch2insert);//setting family relationship
vector<Branch*>::iterator begin=tree_branches.begin();//creating iterators to manipulate vector elements
unsigned int inserting_position=u_parent_index+1;//initializing inserting_position
tree_branches.insert(begin+inserting_position,branch2insert);//inserting new branch
}
void Tree::removeBranch(int branch_index){
int N=tree_branches.size();
unsigned int u_branch_index=branch_index;
Branch* branch2remove=tree_branches.at(u_branch_index);
branch2remove->removeParent(); //removing parenthood link, if branch2remove is the trunk nothing will be done
if(branch_index!=0){//removing childhood link between parent and branch_index
Branch* branch2removeParent=branch2remove->getParent();
branch2removeParent->removeChild(branch2remove);
}
int last_descendant_index=Tree::getLastDescendantIndex(branch_index);
cout<<"The branch to remove is "<<branch_index<<", its last descendant index is "<<last_descendant_index<<", the size of the tree is "<<N<<".\n";
branch2remove->removeDescendants();//removing family links for all descendents
if(last_descendant_index==N-1){
vector<Branch*>::iterator begin=tree_branches.begin();
tree_branches.erase(tree_branches.begin()+u_branch_index,tree_branches.end());
}
else{
vector<Branch*>::iterator begin=tree_branches.begin();
unsigned int u_last_descendant_index=last_descendant_index;
tree_branches.erase(tree_branches.begin()+u_branch_index,tree_branches.begin()+u_last_descendant_index+1);//removing the considered branch and its descendents from the tree vector
}
}
test.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <typeinfo>
#include <vector>
#include <map>
#include <string>
#include "tree.h"
using namespace std;
int main(){
Tree tree;
tree=Tree();
for(int i=0;i<5;i++){
int N=tree.getNumberOfBranches();
for(int j=0;j<N;j++){
tree.addBranch(j);
tree.addBranch(j);
}
}
tree.removeBranch(21);
tree.removeBranch(30);
tree.removeBranch(50);
return 0;
}
to compile:
g++ -Wall -pedantic -c
1) If I understood well, the fact that the only attributes of Tree class are a vector and a map, makes it unnecessary to declare a destructor, a copy-assignement operator and a copy constructor, because the memory is managed "inside" the vector and map templates.
You are wrong here, as the memory which is managed inside the vector is only the storage for the addresses of branches(Branch *). When you insert some branch you call something like tree_branches.push_back(new Branch), don't you? Thus, you will need to call the corresponding delete somehow, otherwise the default destructor of the tree won't take care of calling the destructors of the Branches.
A quick fix for your code could be switching from Branch * to shared_ptr<Branch>. In such way, when the tree_branches vector is destroyed, the shared_ptr's will also be destroyed and when the latest shared_ptr to any Branchis destroyed, also the pointed Branch will be.
would stocking the int hierarchy inside a vector avoid declaring a destructor and company?
It would change jack squat, as the Branches default destructors still would not be called, and so the destructors of the Branches members would never be called.
Finnally there isn't a memory leak. Thanks #Yunnosch for mentionning Valgrind, I wasn't aware this kind of tool existed.
#Davide I accepted your answer since it provided an alternative to what I've done, even if apparently there aren't problems with the management of the memory in my code.
The code I posted has a problem in function Tree::getLastDescendantIndex.
hey i created an abstract class called "Node" and and class NodeBlock that implements the Node class. in my main class i need to print the values that inside the NodeBlock this is some of my code for the main class:
//receving the fasteset route using the BFS algorithm.
std::stack<Node *> fast = bfs.breadthFirstSearch(start, goal);
/*print the route*/
while (!fast.empty()) {
cout << fast.top() << endl;
fast.pop();
}
Node:
#include <vector>
#include "Point.h"
#include <string>
using namespace std;
/**
* An abstract class that represent Node/Vertex of a graph the node
* has functionality that let use him for calculating route print the
* value it holds. etc..
*/
class Node {
protected:
vector<Node*> children;
bool visited;
Node* father;
int distance;
public:
/**
* prints the value that the node holds.
*/
virtual string printValue() const = 0;
/**
* overloading method.
*/
virtual string operator<<(const Node *node) const {
return printValue();
};
};
NodeBlock.h:
#ifndef ADPROG1_1_NODEBLOCK_H
#define ADPROG1_1_NODEBLOCK_H
#include "Node.h"
#include "Point.h"
#include <string>
/**
*
*/
class NodeBlock : public Node {
private:
Point point;
public:
/**
* prints the vaule that the node holds.
*/
ostream printValue() const override ;
};
#endif //ADPROG1_1_NODEBLOCK_H
NodeBlock.cpp:
#include "NodeBlock.h"
using namespace std;
NodeBlock::NodeBlock(Point point) : point(point) {}
string NodeBlock::printValue() const {
return "(" + to_string(point.getX()) + ", " + to_string(point.getY());
}
i deleted all the unnecessary method of those class. now i'm trying to overload the << operator so when i top.() from the stack it will and assign it to the "cout" it will print the string of the point.
but my current output is:
0x24f70e0
0x24f7130
0x24f7180
0x24f7340
0x24f7500
which as you know is the address. thanks for the help
What you're looking for is a << operator that has an ostream on the left and a Node on the right, and evaluates to the same ostream. Thus, it should be defined like this (outside of the Node class):
std::ostream& operator<<(std::ostream& out, const Node& node) {
out << node.printValue();
return out;
}
Then you need to make sure that you're couting a Node, not a Node*:
cout << *fast.top() << endl; // dereference the pointer
I am trying to get this to return a string, but i am having trouble getting it working. The goal is to have a doubly-linked list that points to strings. I am not allowed to have it contain the string, it must point to it instead. Currently i am having trouble getting my program to use it. For example, it always seems to return what the command was, and its confusing me and hard to explain.
#ifndef DOUBLY_LINKED_LIST_H
#define DOUBLY_LINKED_LIST_H
#include <iostream>
#include <string>
//#include "Playlist.h"
using namespace std;
class DoublyLinkedList
{
public:
DoublyLinkedList();
~DoublyLinkedList();
bool empty();
void append(string& s);
void insertBefore(string& s);
void insertAfter(string& s);
void remove(string& s);
void begin();
void end();
bool next();
bool prev();
bool find(string& s);
const string& getData();
private:
class Node
{
public:
Node (string *data, Node *next, Node *prev)
{m_data = data; m_next = next; m_prev = prev;}
string *m_data;
Node * m_next;
Node * m_prev;
};
Node *m_head;
Node *m_tail;
Node *m_current;
};
#endif // DOUBLYLINKEDLIST_H_INCLUDED
.cpp file>>>>
const string& DoublyLinkedList::getData()
{
string *m_tmp;
m_tmp = m_current->m_data;
cout << m_current->m_data << endl;
//cout << "returning: " << m_current->m_data << endl;
// return m_current->m_data;
return *m_tmp;
}
void DoublyLinkedList::append(string &s)
{
if (!m_head)
{
m_head = new Node(&s, NULL, NULL);
m_tail = m_head;
m_current = m_head;
}
else
{
m_tail->m_next = new Node (&s, NULL, m_tail);
m_tail = m_tail->m_next;
m_current = m_tail;
}
}
Consider the following example:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void store_value(vector<string*>& vec, string& str)
{
vec.push_back(&str);
}
void create_and_store_value(vector<string*>& vec)
{
string str("This string is temporary");
store_value(vec, str);
}
int main(int argc, char** argv)
{
vector<string*> pointers;
create_and_store_value(pointers);
cout << *pointers.back() << endl;
string myPersistingString("Yay");
store_value(pointers, myPersistingString);
cout << *pointers.back() << endl;
return 0;
}
This example contains two function, a function store_value which behaves similar to your append function (except, for the purposes of this example working on a std::vector) and a second function showing the possible danger of taking the address of a reference (this is one of the possible hazards that I believe Manu343726 and Mats Petersson are preluding too).
The reason this is dangerous is because the string declared inside create_and_store_value does not persist after the completion of the function. This means that we are left with a pointer to memory which is probably not what we expect. On the other hand, creating a string inside the main function is fine, since the string there persists until the end of the program.
For us to help you further, I would suggest editing your question to give us an example of how you are calling your function. I would suggest pasting a minimal striped down version of your code including an example of how you are calling append, something like:
#include <blah>
class DoubleLinkedList
{
DoubleLinkedList(void)
{
// Include these inline to make copying and pasting simpler.
}
~DoubleLinkedList(void)
{
...
}
append(...) { ... }
getData(...) { ... }
};
int main(int argc, char** argv)
{
DoubleLinkedList dll;
// Show us how you are using this list
return 0;
}
In the above, replace the comments and dots with the relevant code.