I'd like to be able to access all of the nodes in my Mesh class from the Element class. I believe I have both classes correctly setup to do this, but I'm not clear on the best practice to initialize the static pointer to Mesh inside of Element. What do you normally do for this?
Thanks!
The code (so far)
//Mesh.h
#pragma once
#ifndef MESH_H
#define MESH_H
#include <vector>
#include <map>
#include "Eigen/Eigen"
#include "Element.h"
#include "Node.h"
class Mesh {
public:
std::vector< Node* > m_Nodes;
std::vector< Element* > m_Elements;
Eigen::MatrixXd m_K;
Eigen::VectorXd m_F;
Eigen::VectorXd m_u;
void Mesh::LoadFile(wchar_t* MeshFile);
};
#endif
//Element.h
#pragma once
#ifndef ELEMENT_H
#define ELEMENT_H
#include <vector>
class Mesh;
class Element {
public:
static Mesh * m_Parent;
static int m_ElementCount;
int m_ElementIndex;
std::vector< int > m_ElementNodes;
};
#endif
I lack reputation to comment on your post, so I have to post here.
Why not just have each Element instance have its own pointer to its parent? Each pointer can point to the same Mesh object. Is the memory savings really that important?
Even if you do end up with a singleton mesh, if, in the future, you do want to extend to multiple meshes, each with a group of elements, the change will be easier to do.
If you do need to have a static pointer to the parent mesh, you could encapsulate construction of the elements in a method of Mesh, and set the parent pointer to this in Mesh's constructor.
You have to define the static pointer (in any source file; not in *.h):
Mesh* Element::m_Parent; // initialized to NULL by the system
In addition, to initialize it, use the following syntax :
Element::m_Parent = whatever;
I tried not to change anything in your class design, but you should think about which member functions and fields should be static and which should not; the design doesn't look convenient now.
Related
I am trying to make a Graph in C++, and I have almost no code, but I get some weird error. If I just run code, I get Process finished with exit code 0, but if I take a look at debugger (specifically, it I try to check my graph object), I see Cannot access memory at address 0x....
I am new to C++, so I cannot really get what has given me this error. Also, I almost don't have code yet & these few lines I took from my previous program which worked without this problem.
Anyway, I have a vertex class:
#ifndef P2_VERTEX_H
#define P2_VERTEX_H
class vertex {
private:
int id;
public:
explicit vertex(int id) { this->id = id; }
int get_id() { return id; }
};
#endif //P2_VERTEX_H
And then a graph header:
#ifndef P2_GRAPH_H
#define P2_GRAPH_H
#include <vector>
#include "vertex.h"
class graph {
private:
int N; // number of vertices
int M; // number of edges
std::vector<vertex*> vertices; // vector of vertices
std::vector<vertex*> *adj; // ARRAY of vectors of vertices
public:
graph(int n_vert);
graph(bool from_file, const char *file_name);
};
with implementation of graph:
#include "graph.h"
#include <iostream>
#include <fstream>
#include <sstream>
graph::graph(int n_vert) {
N = n_vert;
}
And I instantiate graph as:
#include "graph.h"
int main() {
graph g = graph(4);
return 0;
}
Specifically, I get this mistake if I uncomment std::vector<vertex*> *adj; in a graph header. While I realise that this is probably not the perfect way of storing adjacency list, I fail to see why it gives me an error I mentioned. Especially since I used it before, just instead of std::vector<vertex*> I had std::vector<edge*> where edge was some struct. I tried also to have std::vector<vertex> isntead of std::vector<vertex*> but I have the same error.
Upd:
If I initialize adj in constructor:
adj = new std::vector<vertex*>[N];
I get Duplicate variable object name in debugger after reaching this line.
The issue is that you never initialized adj so it will point to a random location in memory.
You have to initialize the pointer to nullptr to get rid of it.
For example, in the constructor initialization list:
graph::graph(int n_vert) : N(n_vert), adj(nullptr)
{}
By the way you forgot to initialize other field members.
Okay, I may be doing this wrong, but I am at my wits end.
I have a vector of shared_ptr of my node class that I pass around for various things, my node class has a vector of share_ptr of it neighbors of type node.
I have a class that generates the mesh of nodes for me, and returns a std::vector<std::shared_ptr<Node>> nodes, and a significant std::shared_ptr<Node> significant node.
I then pass this vector into an indexer that creates a second list that is a subset of the first of about 10% the size, which it returns as std::vector<std::shared_ptr<Node>> indexedNodes.
After these are created, I pass them into another object that keeps them for later reference.
Then a modifier class gets the a single random node from the indexedNodes, and uses that to walk through the node neighbors modifying a height value.
Later, when I go to export these out, the values show up as 0/initialized.
Somethings to note, I pass the data into the functions and return with just std::vector<std::shared_ptr<Node>> which I figured is my issue, I am just not sure how to properly pass a container of my shared_ptr so that I don't make copies.
If more info is needed, let me know. I am looking for an example or a reference that I can understand.
Sorry for the code, it is not beautful, and I have it using Dynamically Loaded Libraries.
The function where the work is done:
void cruthu::Cruthu::Run() {
std::shared_ptr<cruthu::ITeraGen> teraGen(this->mSettings.TeraGen.Factory->DLGetInstance());
std::vector<std::shared_ptr<cruthu::Node>> nodes(teraGen->Create());
std::shared_ptr<cruthu::Node> significantNode(teraGen->GetSignificantNode());
std::vector<std::shared_ptr<cruthu::IIndexer>> indexers;
for(const auto indexer : this->mSettings.Indexers) {
indexers.push_back(indexer.Factory->DLGetInstance());
}
std::vector<std::shared_ptr<cruthu::Node>> indexedNodes(indexers.at(0)->Index(nodes));
std::shared_ptr<cruthu::ITera> tera(this->mSettings.Tera.Factory->DLGetInstance());
tera->SetNodes(nodes);
tera->SetIndexedNodes(indexedNodes);
tera->SetSignificantNode(significantNode);
for(const auto & formaF : this->mSettings.Formas) {
std::shared_ptr<cruthu::IForma> forma(formaF.Factory->DLGetInstance());
forma->SetNode(tera->GetIndexedNode());
forma->Modify();
std::cout << std::to_string(tera->GetIndexedNode()->GetHeight()) << std::endl;
}
this->CreateImage(tera);
}
TeraGen:
#ifndef CRUTHU_ITERAGEN_HPP
#define CRUTHU_ITERAGEN_HPP
#include <cruthu/Node.hpp>
#include <vector>
namespace cruthu {
class ITeraGen {
public:
virtual ~ITeraGen() = default;
virtual std::vector<std::shared_ptr<cruthu::Node>> Create() = 0;
virtual std::shared_ptr<cruthu::Node> GetSignificantNode() = 0;
};
} // namespace cruthu
#endif
Tera:
#ifndef CRUTHU_ITERA_HPP
#define CRUTHU_ITERA_HPP
#include <cruthu/IIndexer.hpp>
#include <cruthu/Node.hpp>
#include <memory>
#include <vector>
namespace cruthu {
class ITera {
public:
virtual ~ITera() = default;
virtual void SetNodes(std::vector<std::shared_ptr<cruthu::Node>>& nodes) = 0;
virtual void SetIndexedNodes(std::vector<std::shared_ptr<cruthu::Node>>& indexedNodes) = 0;
virtual void SetSignificantNode(std::shared_ptr<cruthu::Node> significantNode) = 0;
virtual std::vector<std::shared_ptr<cruthu::Node>>& GetNodes() = 0;
virtual std::vector<std::shared_ptr<cruthu::Node>>& GetIndexedNodes() = 0;
virtual std::shared_ptr<cruthu::Node> GetIndexedNode() = 0;
};
} // namespace cruthu
#endif
Indexer:
#ifndef CRUTHU_IINDEXER_HPP
#define CRUTHU_IINDEXER_HPP
#include <cruthu/Node.hpp>
#include <memory>
#include <vector>
namespace cruthu {
class IIndexer {
public:
virtual ~IIndexer() = default;
virtual std::vector<std::shared_ptr<cruthu::Node>> Index(std::shared_ptr<cruthu::Node> node) = 0;
virtual std::vector<std::shared_ptr<cruthu::Node>> Index(std::vector<std::shared_ptr<cruthu::Node>>& nodes) = 0;
};
} // namespace cruthu
#endif
Forma:
#ifndef CRUTHU_IFORMA_HPP
#define CRUTHU_IFORMA_HPP
#include <cruthu/Node.hpp>
namespace cruthu {
class IForma {
public:
virtual ~IForma() = default;
virtual void SetNode(std::shared_ptr<cruthu::Node> node) = 0;
virtual void Modify() = 0;
};
} // namespace cruthu
#endif
I did update and try adding references in in between, which is why they now have references in places. I still have the same issue.
As user Remy Lebeau stated please provide a minimal, complete and verifiable example.
As you stated you are passing a std::vector<std::shared_ptr<Node>> around from one class to another or from one function to another and that they are not updating and are 0 initialized. From the behavior that you are describing I then have a question for you, I'm posting this as an answer as it would be too long for a comment.
Does your function declaration/definition that accepts the vector or shared pointers above look something like this:
void someFunc( std::vector<shared_ptr<Node> nodes ) { ... }
or does it look something like this:
void someFunc( std::vector<shared_ptr<Node>& nodes ) { ... }
I ask this because it makes a difference if you are passing the container around by value as opposed to by reference.
This is not (yet) a answer, but questions to pin down the problem, since not enough implementation is provided.
One possible problem (hard to say without seeing the implementation...) is that you create the nodes in top of the Run() function:
std::vector<std::shared_ptr<cruthu::Node>> nodes(teraGen->Create());
Then you pass that function as reference in this call:
tera->SetNodes(nodes);
What does tera do with the nodes? Passing by reference means that the count of the shared_ptr:s isn't incremented.
what does this->CreateImage(tera) do?
Are the nodes used after Run() has finished?
I could not get it going with the comments from above, this is mainly my problem of not being able to provide adequate information.
With that said, I re-worked the code to instead pass a cruthu::Tera object around as a shared pointer and exposed the vectors as public members of the class. This is something I will revisit at a later date, as this implementation is not something I feel happy about.
The code is on github, unfortunately it is my thesis work, so I could no longer wait.
If people feel the desire to still attempt an answer, I will work with them.
I have an Object class and ObjectManager class that is supposed to hold pointers to Objects created on the heap and is in charge of housekeeping. i.e., (I don't want to have pointers to temporary Objects, for instance when an object is passed to a function by value). I'd like to do some process on the items in the ObjectManager class and later release the memory.
Please consider the following files:
"Object.h" file
#pragma once
#include<algorithm>
#include "ObjectManager.h"
class ObjectManager;
class Object{
private:
int value;
static bool heap_flag;
public:
Object() {
if (heap_flag) {
heap_flag = false;
ObjectManager::vo.push_back(this);
}
}
~Object() {}
void* operator new (size_t sz){
heap_flag = true;
return malloc(sz);
}
void setValue(int v) { value = v; }
};
and "ObjectManager.h"
#pragma once
#include "Object.h"
#include <vector>
using namespace std;
class Object;
class ObjectManager{
private:
ObjectManager() {}
public:
static vector <Object*> vo; // vector that holds pointers to all objects created on heap
static void releaseObjects() {
size_t index = 0;
for (auto o : vo){
// iterate through the vector and delete the object create on heap
delete o;
vo[index] = NULL;
index++;
}
}
};
finally in the client code:
#include <iostream>
#include "Object.h"
#include "ObjectManager.h"
using namespace std;
bool Object::heap_flag = false;
vector<Object*> ObjectManager::vo;
void process_Heap_objects (vector<Object*>) {
// ... code to iterate through the elements of a vector and do some process
}
int main() {
Object o; // created on stack
Object* po = new Object(); // created on heap
ObjectManager::vo[0]->setValue(100);
process_Heap_Objects(ObjectManager::vo);
ObjectManager::releaseObjects();
return 0;
}
when I compile this file I get the following warning in VS2013 -> "warning C4150: deletion of pointer to incomplete type 'Object'; no destructor called
1> Objectmanager.h: see declaration of 'Object'"
the code compiles fine and works as expected though.
two questions:
1- what does the warning mean?
2- is this a good design? is there a better way to achieve this? what are your thoughts?
You can't call a destructor on a forward declared class.
You must put the destructor call in a compilation unit where it can see the declaration of the destructor (e.g. where you #include the Object.h).
Also, stylistic tips:
On pass by value:
If the object is not going to be mutated or copied by the method, pass by const ref foo (const Object& bar) {}
If the object is going to be mutated but not copied by the method, pass by reference foo (Object& bar) {}
If the object is going to be copied by the method, pass by value
If the method takes possession of the object, pass by pointer
pragma once is not officially part of the standard, and rarely offers faster compilation in current generation compilers. Most style guides recommended to use include guards:
#ifndef SOME_NAME
#define SOME_NAME
... body ...
#endif
Your problem is you are defining and implementing both Object and ObjectManager in the header files. This creates a circular dependency because each header file includes the other.
A better approach would be to only have the class definitions in the headers and the bodies of the methods in cpp files.
The warning you're receiving is due to Object not being defined. Because you have #pragma once you aren't seeing the error you should be seeing (the effect of the circular dependency.) This is preventing the ObjectManager from seeing how the Object class is defined.
I have a memory management question. For one of my projects I am building an interpreter for a small programming language. One of the first steps is to model and build an Abstract Syntax Tree.
As of now, I'm using smart pointers to manage the lifetime of nodes, and I figured that every parent node is the owner of it's children, but it also must be shared with the environment (for example, to know which part of the tree a method's body belongs to) and with the garbage collector, which must keep a list of all references to enact the naïve mark and sweep algorithm. Therefore, I am using std::shared_ptr to keep track of the references. For instance, here's an example of a Block node, which basically represents a lambda expression:
#ifndef NAYLANG_BLOCK_H
#define NAYLANG_BLOCK_H
#include <model/ast/expressions/Expression.h>
#include <model/ast/declarations/Declaration.h>
#include <memory>
#include <vector>
namespace naylang {
#define BlockPtr std::shared_ptr<Block>
class Block : public Expression {
std::vector<std::shared_ptr<Statement>> _body;
std::vector<std::shared_ptr<Declaration>> _params;
public:
Block() = default;
void accept(Evaluator &evaluator) override;
const std::vector<std::shared_ptr<Statement>> &body() const;
const std::vector<std::shared_ptr<Declaration>> ¶ms() const;
void addStatement(std::shared_ptr<Statement> statement);
void addParameter(std::shared_ptr<Declaration> param);
};
} // end namespace naylang
#endif //NAYLANG_BLOCK_H
As you can see, this node is the owner of all it's parameters and body expressions, and has accessors so that the Evaluator can traverse the tree.
Now, the problem comes when trying to have nodes that are bound at evaluation time to other nodes, for example:
#ifndef NAYLANG_REQUEST_H
#define NAYLANG_REQUEST_H
#include <model/ast/expressions/Expression.h>
#include <string>
#include <memory>
#include <vector>
#include <model/ast/declarations/MethodDeclaration.h>
namespace naylang {
class Request : public Expression {
std::string _name;
std::vector<ExpressionPtr> _params;
// We use naked pointers because we don't want to worry
// about memory management, and there is no ownership
// with the declaration.
const MethodDeclaration *_binding;
public:
Request(const std::string &methodName);
Request(const std::string &methodName, const std::vector<ExpressionPtr> params);
void accept(Evaluator &evaluator) override;
void bindTo(const MethodDeclaration *_binding);
const std::string &method() const;
const std::vector<ExpressionPtr> ¶ms() const;
const MethodDeclaration &declaration() const;
};
} // end namespace naylang
#endif //NAYLANG_REQUEST_H
As you can see, bindTo() is called when a BindingEvaluator (subclass of Evaluator) evaluates a Request object, long after it's constructed. However, I am really not sure about what the _binding parameter should look like. Here's a part of the Evaluator interface:
#ifndef NAYLANG_EVALUATOR_H
#define NAYLANG_EVALUATOR_H
#include <model/ast/Statement.h>
namespace naylang {
class Request;
class Block;
class Evaluator {
public:
Evaluator() = default;
virtual ~Evaluator() = default;
// Methods left blank to be overridden by the subclasses.
// For example, a Binding Evaluator might be only interested in
// evaluating VariableReference and Request Statements
virtual void evaluate(Request &expression) {}
virtual void evaluate(Block &expression) {}
};
}
#endif //NAYLANG_EVALUATOR_H
Here's my rationale:
The reference should be polymorphic, and therefore should be some kind of pointer.
The reference does not denote ownership, and therefore it should not be a std::shared_ptr.
In addition, we need the Visitor pattern, so every node has the function void accept(Evaluator &evaluator);. As a node cannot return a shared_ptrof itself, we cannot change the interface to something like virtual void evaluate(std::shared_ptr<Request> &expression) {}.
Thus, naked pointers. I really want to get this right before moving on, because it's a ton of code to change every time I rethink it (ASTs are verbose...)
Thank you in advance.
Let's say I have two member variables called attribute name and value and I want to store them inside a vector called attributes. I know I can create an object so let's say I had a class called Element and then I created an object called Element* Element_object Now I want to store the attribute name and attribute value inside of Element_object vector. I know there's a function called push_back() that helps you to do so. I was thinking that I would something like this attributes.push_back(attribute_value);except that won;t work because attribute is type element pointer and attribute value is a string type. Should I change the type of my vector attribute from element* to a string and then do attributes.push_back(attribute_value);I want to store multiple attributes inside the object vector so I'm assuming that in order to store multiple attributes inside element_object vector I would keep using push_back()?
My .h file looks like this:
#ifndef Header_h
#define Header_h
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
class Element{
public:
void set_attribute_name(string temp_attribute_name);
string get_attribute_name();
void set_attribute_value(string temp_attribute_value);
string get_attribute_value();
private:
/**Member variables**/
vector<Element*> attributes;
string attribute_name;
string attribute_value;
};
#endif /* Header_h */
you can create a separate class or a simple struct will do.
you cannot push individual struct members to vector. you need to push the entire object/pointer to obj.
struct keyvalue
{
std::string attribute_name;
std::string attribute_value;
};
vector<keyvalue*> vecKeyValue;
in implementation file:
keyvalue* pkval = new(std::nothrow) keyvalue;
pkval->attribute_name = "name";
pkval->attribute_value = "value";
vecKeyValue.push_back(pkval);