C++ Instantiation - c++

I have Vector class, representing a 3D point, written as follows in Vector.h:
class Vector {
public:
float x,y,z;
Vector(float _x=0.0,float _y=0.0,float _z=0.0){x=_x;y=_y;z=_z;};
operator float *() { return &x;};
};
I also declare a extern vector<Vector>model_vertices; on model.h
On a model.cpp file I implement Vector.h and declare a std::vector<Vector>model_vertices; globally (yes, I know the vector/Vector thing is confusing, but I must use the Vector naming for consistency).
On model.cpp, when initializing the contents of this vector I use a for loop with the following content:
float X,Y,Z;
offFileStream>>X;
offFileStream>>Y;
offFileStream>>Z;
Vector v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=v;
I get the following error:
error C2440: 'initializing' : cannot convert from 'Vector *' to 'Vector'
Why?

The error is on this line:
Vector v=new Vector(X,Y,Z);
v is of type Vector, but new Vector(X,Y,Z) returns a Vector*:
What you probably wanted instead is just:
Vector v(X,Y,Z);
As a side note, I didn't see you initialize a size for the model_vertices. So you may want to use push_back() instead.

It's not quite clear what you're trying to achieve, but perhaps you're overthinking this.
First off, please forget the keyword new. Just pretend it doesn't exist. (By the time you'll need it, you'll know enough C++ to realize that you can ignore this post.)
Second, you can improve your class constructor to use an initializer list:
Vector(float _x = 0.0, float _y = 0.0, float _z = 0.0)
: x(_x), y(_y), z(_z)
{ }
Third, to populate a vector, just insert temporaries directly:
std::vector<Vector> v;
float x, y, z;
while (get_values(x,y,z)) // or any sort of loop you like
{
v.push_back(Vector(x,y,z));
}
If you have a recent version of C++, you can use the more efficient emplacement instead:
v.emplace_back(x, y, z); // no temporary

Vector v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=v;
should be
Vector *v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=*v;
new() allocated from the heap and it returns a pointer to an object.
If you want to call the constructor and allocate on the stack, do this instead.
Vector v(X,Y,Z);

The new operator can only be used when asigning to a pointer. If you just want to have an object v of type vector then you should use:
Vector v(X,Y,Z);
If you would like to have a pointer to Vector object then you should use:
Vector *v=new Vector(X,Y,Z);

Related

Error with initialization of 2d arrays in C++

So, I have declared a typedef as:
typedef float Matrix4[4][4];
when I try to Initialize it as:
void getXRotationMatrix(float theta, Matrix4 ans) {
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
}
it gives an error:
too many initializer values
however, it works when I initialize it as:
void getXRotationMatrix(float theta, Matrix4 ans) {
float a[4][4] = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
ans = a;
}
It doesn't give any error. Can someone please explain?
when I try to Initialize it as: ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Note that
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
is an assignment and not an initialization. On the other hand,
float a[4][4] = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
is an initialization and so works.
The correct way to initialize ans would be:
Matrix4 ans{ {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Also note that array assignment is not possible in C++.
There is also the concept of type decay that you have to take care(into account) for ans = a;. In particular, both ans and a are actually pointers and so when you write
ans = a;
you're actually assigning one pointer to another instead of one array to another.
You can use a std::vector as follows:
typedef std::vector<std::vector<float>> Matrix4;
void getXRotationMatrix(float theta, Matrix4 ans) {
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
}
Error with initialization of 2d arrays in C++
when I try to Initialize it as:
ans = { {0,0,0,0},{1,1,1,1},{0,0,0,0},{1,1,1,1} };
Problem 1: That's not initialisation. That's assignment. Arrays cannot be assigned, but that's irrelevant due to next point.
Problem 2: ans is not an array. Function parameters are never arrays. Although you wrote it as an array, it has been adjusted to be a pointer to the element of the said array type. And the braced-init list that you provided is not a valid right hand argument for assigning a pointer.
however, it works when I initialize it as:
ans = a;
It becomes well-formed because a is a valid expression to assign to the pointer. The array will implicitly convert to a pointer to first element.
But the pointer is local to the function, so that function has no side-effects whatsoever.
I recommend returning instead of attempting to modify the parameter. Now, arrays cannot be returned in C++, but there is a simple solution: You can return class instances, and classes may contain array as a member. There is a class template for such array wrapper in the standard library. It's called std::array. Example:
std::array<float[4], 4>
getXRotationMatrix() {
return {{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{1,1,1,1},
}};
}

Faulty vector constructor in MSVC? (Vector of raw arrays) [duplicate]

Could someone tell what is the correct way to work with a vector of arrays?
I declared a vector of arrays (vector<float[4]>) but got error: conversion from 'int' to non-scalar type 'float [4]' requested when trying to resize it. What is going wrong?
You cannot store arrays in a vector or any other container. The type of the elements to be stored in a container (called the container's value type) must be both copy constructible and assignable. Arrays are neither.
You can, however, use an array class template, like the one provided by Boost, TR1, and C++0x:
std::vector<std::array<double, 4> >
(You'll want to replace std::array with std::tr1::array to use the template included in C++ TR1, or boost::array to use the template from the Boost libraries. Alternatively, you can write your own; it's quite straightforward.)
Use:
vector<vector<float>> vecArray; //both dimensions are open!
There is no error in the following piece of code:
float arr[4];
arr[0] = 6.28;
arr[1] = 2.50;
arr[2] = 9.73;
arr[3] = 4.364;
std::vector<float*> vec = std::vector<float*>();
vec.push_back(arr);
float* ptr = vec.front();
for (int i = 0; i < 3; i++)
printf("%g\n", ptr[i]);
OUTPUT IS:
6.28
2.5
9.73
4.364
IN CONCLUSION:
std::vector<double*>
is another possibility apart from
std::vector<std::array<double, 4>>
that James McNellis suggested.
Every element of your vector is a float[4], so when you resize every element needs to default initialized from a float[4]. I take it you tried to initialize with an int value like 0?
Try:
static float zeros[4] = {0.0, 0.0, 0.0, 0.0};
myvector.resize(newsize, zeros);

Error overloading operator [] for a std vector object

I have a polygon class defined like this:
#include <gVector3.h> // an array containing three floats (x,y,z coordinates)
#include <vector>
class Polygon {
private:
std::vector <gVector3> vertices;
std::vector <gVector3> color;
I overloaded the [] operator for this class like so
gVector3 Polygon::operator [](unsigned int i) const {
return vertices[i];
}
I've written a simple test case:
gVector3 v1(0,0,1), v2(1,1,1), v3(2,0,1);
Polygon *p = new Polygon();
p->push(v1);
p->push(v2);
p->push(v3);
assert(p[0] == v1); // Assume == for the gVector3 class has been defined correctly
Push is defined like so..
void Polygon::push(gVector3 vec){
this->vertices.push_back(vec);
}
Bottom line is that this assertion fails, and I'm not sure why. Perhaps I'm misusing the Vector classes indexing method?
Any insights would be helpful!
p is a pointer, so p[0] is the Polygon that it points to. I'm surprised that it compiled; I guess there must be some strange implicit type conversion.
You almost certainly don't want to be messing around with pointers and new:
Polygon p;
p.push(v1);
p.push(v2);
p.push(v3);
assert(p[0] == v1);
but if you do for some reason, then you'll need to dereference the pointer before applying []
assert((*p)[0] == v1);
p[0] is equivalent to *(p + 0), or just *p, so its just giving you the Polygon object you allocated. You aren't calling operator[] on that object. You need to do (*p)[0] instead, which will first get you the Polygon object and then call operator[] on it.

Dereferencing not working for std::vector<std::vector<double> >

struct myS {
std::vector<std::vector<double> > *A;
}
I want to access the elements of A using indices. I tried this (and also other versions) but it did not work.
struct myS test;
std::vector<double> B = *(test.A)[0];
Reposition your brackets:
std::vector<double> B = (*test.A)[0];
This compiles:
struct myS{
std::vector<std::vector<double> > *A;
};
myS instanceOfMyS;
std::vector<double> B = (*instanceOfMyS.A)[0];
Note
struct myS just declares a type of myS. To declare an instance of the type you need to add the instanceOfMyS afterwords.
You also omitted the <double> in the declaration of B.
However the code above will take a copy of the first element in *instanceOfMyS.A. So you might want a reference instead.
std::vector<double>& B = (*instanceOfMyS.A)[0];
Finally, it looks a bit dodgy that you're using a pointer in your struct (with a pointer you don't allocate the memory to back the vector pointed to be A unless you explicitly allocate the memory, leading to access violations). You might want the following
struct myS{
std::vector<std::vector<double> > A;
};
myS instanceOfMyS;
std::vector<double>& B = instanceOfMyS.A[0];
This will work :
myS myObj;
// Add some stuff in your vector(s) ...
...
// Access your vector
std::vector<double> B = (*myObj.A)[0]; // Don't forget here that it will copy the elements of the vector
Or if you want to access to an item into the second vector :
double B = (*myS.A)[0][0];
Another question : Why are you using a vector in the structure in this case ? In my own opinion, you should not have this pointer in your struct. It should be a value like :
struct myS{
std::vector<std::vector<double> > A;
}
EDIT : small mistakes on dereferencing pointer resolved
You should write (myS->A)[i] to access the ith outer vector: rewrite your line as
std::vector B = (myS->A)[0];
but note that this will take a value copy of the vector.
By the way, you will need to do (myS->A)[i][j] to access the jth element in the ith outer vector,
But why use a pointer in the first place?

C++ Fill a vector with another vector

I have two vectors, and I would like to fill the first one with the second. The vectors are declared like this:
vector<Vec3> firstVector;
Where Vec3 is a struct with float x, y, z.
I have tried liked this with assign:
secondVector.assign(firstVector.begin(), firstVector.end());
But it stops and complains, that there is problem with the end().
I have also tried pushback, but of course it's not working.
As I read before I should do it with assign, but I don't know how to solve it properly.
EDIT:
The error message with insert and assign are the same:
this 0x00000000 ... std::vector > * const
[size] CXX0030: Error: expression cannot be evaluated
[capacity] CXX0030: Error: expression cannot be evaluated
And it points to Visual Studio's vector file to iterator end to the return. With insert it points to iterator begin.
THE CODE:
The first Vector is also part of a struct:
struct o3DModel
{
vector<Vec3> v_Vertices;
};
struct Vec3 {
public:
Vec3() {}
Vec3(float X, float Y, float Z)
{
x = X;
y = Y;
z = Z;
}
float x, y, z;
};
I declare the "o3DModel" struct above in my app class like this and send it to my loader class:
o3DModel *tfTable;
void TheApp::Init()
{
objLoader->ImportOBJ(tfTable, "testcube.obj");
}
The objLoader class, where I successfully fill my "v_Vertices" vector, where "oModel" is the sent "tfTable":
bool OBJLoader::ImportOBJ(o3DModel *oModel, char *strFileName)
{
FillObjData(oModel);
...
return true;
}
void OBJLoader::FillObjData(o3DModel *oModel)
{
oModel->v_Vertices.insert(oModel->v_Vertices.begin(), v_Vertices.begin(), v_Vertices.end());
// This here with insert
outFile2 << oModel->v_Vertices[0].x << "\n";
}
Hope this helps.
If you want secondVector to take on all of the values of firstVector and no others,
secondVector = firstVector;
If you want each of the elements of firstVector to be added to the end secondVector:
secondVector.insert(secondVector.end(),
firstvector.begin(), firstVector.end());
If you want each of the elements of firstVector to be added to the beginning of secondVector:
secondVector.insert(secondVector.begin(),
firstVector.begin(), firstVector.end());
Or if you don't want to do it in the ctor use
secondVector = firstVector
This should work:
vector<Vec3> secondVector(firstVector.begin(), firstVector.end());
That's the case when you're interested in using the vector constructor.
You second vector needs to be declared as a vector of vectors of Vec3 strucs.
vector<vector<Vec3>> secondVector;
secondVector.push_back(firstVector);
Okay, I have solved it, but with a little roundabout. In FillObjData I have created a new Vec3, created an if, gived the first vector x, y, z coordinate to the new Vec3, and pushed the Vec3 into the vector. And when I declared my struct I have declared it real not as a pointer. Now it works perfectly.