This is the code I'm trying to run:
class poly {
public:
int vnum;
vrtx vrts[this->vnum];
};
(Note: The class name "poly" and other class "vrtx" are named as such to approximate the purpose of the problematic snippet. Vrtx is a class with int x, y, z;)
At first, the code didn't contain the "this->" pointer at all. I was confused why it wasn't working, and then realized that "vnum" doesn't mean anything. I needed an object.poly.vnum sort of thing so that I'm referencing a specific value. I tried "this.," "this.poly.," and the displayed "this->," but none of them work. I'm not great with pointers, so any advice would be appreciated!
I've looked at similar questions, but none of them address this issue in such a way that I could make the necessary fix with the information provided.
Here's a code fragment that should help.
class Poly
{
public:
int vnum;
std::vector<vrtx> vrts;
Poly(int capacity)
: vnum(capacity)
{ vrts.resize(vnum);}
};
The above fragment uses std::vector since the std::vector can expand dynamically (at run-time). The constructor uses the resize method to expand the std::vector to the given capacity.
Arrays are a pain to resize during run-time, so use std::vector.
Related
I have two classes called Renderable and Triangle. The latter is supposed to be deriving from the former. I plan to be passing an array and its length into the Triangle constructor, which in turn will pass it to the constructor in the Renderable class that will handle the corresponding parameters. Here are the header files:
Renderable.h
class Renderable {
protected:
const int dataLength = 0;
const float* data[0] ;
public:
Renderable();
Renderable(int dataLength, float* data[]);
virtual void render() const =0 ;
};
Triangle.h
#pragma once
#include <glad/glad.h>
#include "Renderable.h"
class Triangle : public Renderable {
public:
void render() const;
};
So the problem is that the error check gave me invalid base class. I did some research and saw something about arrays' not being able to be an instance variable without specified size but this is still quite confusing to me. Could someone please enlighten me on this?
Also is there a more efficient solution to problems like this?
Thank you!
const float* data[0] ;
This array member declaration is ill-formed. The size of an array variable may not be 0.
Otherwise the example is well-formed (assuming the functions are defined in some translation unit).
Also is there a more efficient solution to problems like this?
Solution is to not declare an array variable of size 0.
So the problem here is that the code design that I was going for is undesirable and I should either use std::vector or making another subtype of the Renderable class with a fixed array length and then extend from it.
i know how to create a stack of vectors or int ,etc. But i dont know how to create a stack of a multidimentional arrays t[n][n] . Whats the way to implement it?
this is my actual implementation which its not working.
char map[20][20];
stack<map> soluciones;
Edit:
I think due my english most of you didnt undestand my question. Imagine i got some kind of a Game map. I am saving each multidimentional array on the stack. Thats my objective saving the map on a stack
Edit 2: im using Visual Studio 2010 Windows form application
In your code example, you use map (the name of your variable) in place of where a type name must stand (in stack<map> template instantiation). However, it won't work, not even if you use the proper type name (in this case you'd have to use typedef, e.g. typedef char TwoDimCharArray[20][20] and then try std::stack<TwoDimCharArray>:
There is still the problem that arrays don't have a default constructor (which std::stack expects); therefore, std::stack cannot be made to directly contain arrays; you'd have to wrap the array inside a class or struct (which can have a default constructor), e.g.:
class TwoDimCharArray
{
public:
// omit if there's nothing to initialize in map, then the
// compiler-generated constructor will be used
TwoDimCharArray()
{
// ... initalize map values
}
// ... provide access methods to map
private:
char map[20][20];
};
std::stack<TwoDimCharArray> soluciones;
Or use Boost.Array or C++11 std::array stuff! If these are available, they are definitely the better and easier choice!
I guess you should define a proper class for the game map. Then the stack of game maps is not a problem.
class GameMap {
public:
...
private:
char map_[1000][1000];
};
Then it wont matter for the stack how you allocate and manage the map data. E.g.
typedef std::stack<GameMap> GameMapStack;
Ddefine a wrapper class for multidimentional arrays like this:
template <class T, int X, int Y>
class Wrapper
{
public:
T array[X][Y];
}
Then use stack<Wrapper<char, 20, 20> >
First create structure and then define an empty multidimensional char array. then close structure and after thar write push and pop operations.
I am writing a program that works with graphs. I am dealing with two types of graphs : "abstract graphs", which consist in abstract vertices with edges, and "planar graphs", in which the vertices have coordinates x,y in the plane (actually I am working with a complex affix z but it does not matter).
I have elected to write an (abstract) Vertex class and a derived class Planar_Vertex as follows in my Vertex.h file - this is not precisely my code, I made it slightly simpler and "translated" it from French ;)
class Vertex
{
public:
Vertex();
int get_label();
void set_label(int label);
void add_neighbor(int label);
bool is_neighbor(int label);
// etc
protected:
int _label;
std::vector<int> _list_neighbors;
};
class Planar_Vertex : public Vertex
{
complex<double> _affix;
public:
Planar_Vertex();
Planar_Vertex(Vertex& V, complex<double> affix);
complex<double> get_affix();
void set_affix(complex<double> affix);
};
Here's my main question. I would like my Planar_Vertex(Vertex& V, complex affix) constructor to have the following effects : 1. Output a Planar_Vertex whose label and list of neighbors are the same as V, and whose affix is given. So far, easy. 2. I would like V to be precisely the abstract Vertex underlying this new object. In other words, if in my main.cpp file I wrote, say,
Vertex V1;
...
Planar_Vertex V2(V1,z)
then I would like that a use of set_label() on V2 will also affect V1 (for example). The way I see it is, in this constructor, I would like to say something like: make the address of V (in memory) the same as that of the Planar_Vertex constructed (and free the memory previously allocated to V). Apparently it is not possible to change the location of a variable in memory though, so I don't know what to do. I am relatively new to C++ and I'm getting lost reading about placement new, std::move, rvalues etc. Does anybody see how to do what I want?
[Edit : To summarize, I want to be able to build an object of the derived class on top of an object of the base class that has already been built.]
Okay, now since I told you guys that much about my implementation of graphs, I thought I'd tell you the rest so you can give me your opinion about it, I hope you don't mind. Obviously you don't have to read the following, if you know the answer to my first question that'd be cool already. So as I told you we're dealing with "abstract graphs", which will consist in abstract vertices, and planar graphs, which consist in planar vertices.
Here's what my Graph.h file looks like:
class Graph
{
public:
Graph();
virtual ~Graph();
virtual std::vector<Vertex*> get_list_vertices();
void add_edge(int label1, int label2);
virtual void add_vertex(Vertex&);
// etc
};
class Abstract_Graph : public Graph
{
std::vector<Vertex*> _list_vertices;
public:
Abstract_Graph();
~Abstract_Graph();
std::vector<Vertex*> get_list_vertices();
void add_vertex(Vertex& V);
// etc
};
class Planar_Graph : public Graph
{
std::vector<Planar_Vertex*> _list_planar_vertices;
public:
Planar_Graph();
~Planar_Graph();
std::vector<Vertex*> get_list_vertices();
std::vector<Planar_Vertex*> get_list_planar_vertices();
void add_vertex(Planar_Vertex& V);
// etc
};
My idea is that the base class Graph will never be instanciated, but I will be able to implement "abstract graph operations" as functions of this base class and they will work on both Abstract_Graph and Planar_Graph objects. This is made possible thanks to the purely virtual function get_list_vertices. Is this a reasonable way to do things? What would you have done?
Thank you very much for for answers in advance.
You can keep a reference (or a pointer) to a Vertex object in your Planar_Vertex class to do what you want if I understood you.
Cut down demo:
#include <iostream>
struct Vertex {
int value;
};
struct Planar_Vertex: public Vertex {
Vertex& vr;
Planar_Vertex(Vertex& v): vr(v) {}
};
int main()
{
Vertex v;
v.value = 1;
std::cout << v.value << std::endl;
Planar_Vertex p = Planar_Vertex(v);
p.vr.value = 2;
std::cout << v.value << std::endl;
}
If you use a reference, it must be initialized in the constructor initialization list. If you use a pointer, you have more flexibility in how you initialize it, but have to worry about null pointers everywhere.
In both cases, you're responsible for making sure that the Vertex outlives the Planar_Vertex.
(Another option is to have a plain Vertex (not a reference or pointer) as a member of Planar_Vertex – you initialize it via Planar_Vertex's constructor, and use it wherever you need. This takes care of the lifetime requirements, but might not be possible in your code.)
For your second part, I don't see anything fundamentally wrong, but it's hard to have an opinion just with what you posted. Inheritance is one way to do this, another would be to use templates. Which one is more appropriate depends on the exact requirements (and your familiarity with both these concepts).
I have C# background and been working with C# for so many years.. Recently, I'm learning C++ and having some difficulties..
Basically, I'm trying to create the linked link class as below. I want to use my class as a data in struct node.
How can I fix this in C++? Thanks.
But it said that i can't use like that.
class Polynomial{
public:
Polynomial(pair<double, int>);
void add(Polynomial);
Polynomial multiply(Polynomial);
void print();
private:
struct node
{
Polynomial data;
node *link;
}*p;
};
Your node struct contains a member variable of type Polynominal, but since node itself is declared inside Polynominal, the declaration of Polynominal isn't complete at that point.
I get the impression that you assume classes in C++ to work just like C#, but they don't. C++ isn't garbage-collected, and it doesn't automatically manage references for you when you use classes. A class in C++ behaves more like a struct in C#, and when you pass or declare it like in your example, it gets copied by value.
Another thing: C++ comes with STL, which contains a range of templates for all sorts of things, including a nice linked list (std::list).
Couple of issues:
Polynomial doesn't have a default constructor, so the only way to create it is by using that custom constructor you have. However, your inner struct contains an object of type Polynomial. How is that supposed to be created? You can't embed objects that don't have a default constructor in classes unless you initialize them specifically in the container's constructor.
Your struct contains an object of the type of the parent class, which you're still in the process of defining! If anything, you need to make that struct its own class.
In general, you seem to do a lot by-value operations. This is very inefficient - you should always pass Polynomial by reference or pointer.
To fix it just use Polynomial &data; instead of Polynomial data; in the struct
Change that to Polynomial *data; and it will work just fine. And therein lies your clue as to what's wrong. Understanding that will bring great enlightenment.
One way of explaining it is that in C++ (unlike C#) a Polynomial and a float behave in exactly the same way with regards to how storage is allocated with them. In C# you can't do new float; (not to be confused with new Float();) and in C++ you can.
The points raised by EboMike are all valid, but just to make it compile (it's still unusable due to the constructability issue):
class Polynomial{
public:
Polynomial(pair<double, int>);
void add(Polynomial);
Polynomial multiply(Polynomial);
void print();
private:
struct node; // forward declaration creates incomplete type
node *p; // OK to have pointer to incomplete type
};
struct Polynomial::node
{
Polynomial data; // class Polynomial is complete now
node *link;
};
I am searching a 2D matrix (or bitmap) class which is flexible but also fast element access. The contents A flexible class should allow you to choose dimensions during runtime, and would look something like this (simplified):
class Matrix
{
public:
Matrix(int w, int h) :
data(new int[x*y]), width(w) {}
void SetElement(int x, int y, int val)
{
data[x+y*width] = val;
}
// ...
private: // symbols
int width;
int* data;
};
A faster often proposed solution using templates is (simplified):
template <int W, int H>
class TMatrix {
TMatrix() data(new int[W*H]) {}
void SetElement(int x, int y, int val)
{
data[x+y*W] = val;
}
private:
int* data;
};
This is faster as the width can be "inlined" in the code. The first solution does not do this. However this is not very flexible anymore, as you can't change the size anymore at runtime.
So my question is:
Is there a possibility to tell the compiler to generate faster code (like when using the template solution), when the size in the code is fixed and generate flexible code when its runtime dependend?
I tried to achieve this by writing "const" where ever possible. I tried it with gcc and VS2005, but no success. This kind of optimization would be useful for many other similar cases.
I'd just go with the first version, myself.
But, if you really want to try to get the best of both worlds, you could have a Matrix class which holds a pointer to a polymorphic implementation type. For common sizes (say up to 4x4), you could point at template instantiations, and for larger you could point at an implementation that handled the general MxN case.
Having said all that, I think all the indirection & virtual calls would negate any performance improvement that might come from the templates. I don't think you can have your cake & eat it too, in this case.
If you're always dealing with data who's size is known at compile time (graphics/geometry vectors for example), you're better off with the template version (possibly storing the data in statically sized (non-heap allocated) arrays). If you need a general capability for arbitrary data, use the dynamic version instead.
Of course your needs may differ, but I'd skip the automatic generation and just go with a plain&simple set of "fixed" versions. E.g. Vector3, Vector4, Matrix3x3, Matrix3x4, and Matrix4x4. I suppose you could derive all of those from the templated version, but it won't make any particular performance difference.
Is there any particular reason why you want to be able to change the dimensions at runtime? Because I would suggest that just copying from one to the other wouldn't be terribly costly for the (what I suspect to be rare) instances when the change needs to occur.
Finally- something that I've seen done is to have named element access as well as the array, but you can only do that with "hard coded" types. Something like:
class Vector3
{
public:
// other stuff...
union
{
struct { float x, y, z; };
float m[3];
};
};
(that may not be entirely legal C++, hack to suit your compiler.)
Oh, even the templated version doesn't need to use new. Just declare the data as float data[W*H]; Getting it out of the heap will be a bigger performance boost than "optimizing out" a bit of math.
Not so much a complete answer, but some info that may help (if you're not already aware of these): Both OpenCV and Boost (uBLAS) have very good (fast/complete/full-featured) matrix implementations. I've not looked inside them to see how they set/get elements or resize after instantiation though.