class constructor with structure array (direct) - c++

UPDATE:
i see im causing much confusion in here, sry bout that guys.. thanks Roman for the idea with the vectors ^^
clarifing my problem: i want to get the structure-array straigth into the created class (in main()) by passing the integers as an parameter(i dont want to create global or local variables for dem arrays) and copying them into the class-member
the problem is im failing at the initialization of the class, my attempt:
struct _Note
{
int nFrequenz;
int nTakt;
};
class _Chart
{
public:
_Chart( std::vector<_Note> vNotes )
{
for( int i = 0; i < vNotes.size(); i++ )
this->_chart.push_back( vNotes[i] );
}
private:
std::vector<_Note> _chart;
};
void main()
{
_Chart x(
{ {1,2}, {2,3} }
);
// not working, wrong initialization
// still confused about the brackets ^^
getchar();
}

When passed as a parameter struktur p[] decays to a pointer (similar to struktur* p). The size of this pointer will definitely not be what you're looking for in determining the number of elements.
Instead, why not provide a two iterator constructor similar to the standard containers?

You need to pass the element count too:
klasse( struktur p[], size_t count )
{
_chart = new struktur[count];
// copy array in one shot as no deep copy is needed here.
memcpy(_chart, p, count * sizeof(struktur));
}

An array decays to a pointer when passed. So, you must pass the count of elements in the array as an additional parameter to the function. However, in this scenario, you have an option.
Move the glob definition to above the klasse declaration. Then in the constructor you should be able to get the count of objects with sizeof(glob)/sizeof(struktur);. You should be able to dynamic allocate and do a member wise copy there after.

Why not to use the std::vector container template?
class klasse
{
public:
klasse(std::vector<struktur>& strs)
{
_chart = new struktur[strs.size()];
for( int i = 0; i < strs.size(); i++ )
{
this->_chart[i] = strs[i];
}
}
private:
struktur* _chart;
};
And in main():
void main()
{
std::vector<struktur> myStructs;
myStruct.push_back(glob[0]);
myStruct.push_back(glob[1]);
myStruct.push_back(glob[2]);
klasse y(myStructs);
getchar();
}
This is simple and elegant.
[Upd.] Yes, here in your example sizeof(p) will be equals to sizeof(uintptr_t) because p is a pointer type.

Related

C++ error:Assignment of read-only location

Please help me to find the problem, I am totally lost why I can't modify my list. As you can see I did not declared anything as const..
Here is the code:
struct Carte
{
Carte(initializer_list<initializer_list<int>> iInp){}
initializer_list<initializer_list<int>> aVect;
};
.....
void changeValue(Carte& iCarte, int iValA, int iValB)
{
initializer_list<initializer_list<int>> carte = iCarte.aVect;
initializer_list<initializer_list<int> >::iterator carte_iterator;
initializer_list<int>::iterator carteRow_iterator;
//changing the value
int aLocalI = 0;
int aLocalJ = 0;
for(carte_iterator = carte.begin();carte_iterator!=carte.end();++carte_iterator)
{
if (aLocalI == iValA)
{
for(carteRow_iterator = (*carte_iterator).begin();carteRow_iterator!=(*carte_iterator).end();++carteRow_iterator)
{
if (aLocalJ == iValB)
{
*carteRow_iterator = 1; // ERROR HERE
}
aLocalJ++;
}
}
aLocalI++;
}
}
Many thanks in advance,
Julia
From http://en.cppreference.com/w/cpp/utility/initializer_list:
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T.
The elements of an initializer_list are always const, and thus *carteRow_iterator is const.
If you want a modifiable list of objects, use std::vector or std::array.

Template array class of pointers

I encountered an issue that I have been trying to solve for some time, and simply couldn't do it. Here is the scenario:
1) I have an Template array class that look something like this
//code taken from http://www.learncpp.com, much appreciation for Alex
#ifndef ARRAY_H
#define ARRAY_H
#include <assert.h> // for assert()
template <typename T>
class Array {
private:
int m_nLength;
T *m_ptData;
public:
Array() {
m_nLength = 0;
m_ptData = 0;
}
Array(int nLength) {
m_ptData= new T[nLength];
m_nLength = nLength;
}
~Array() {
delete[] m_ptData;
}
void Erase() {
delete[] m_ptData;
m_ptData= 0;
m_nLength = 0;
}
T& operator[](int nIndex) {
assert(nIndex >= 0 && nIndex < m_nLength);
return m_ptData[nIndex];
}
int GetLength() { return m_nLength; }
friend ostream& operator<<(ostream& out, const Array<T>& n) {
for(int i=0; i<n.m_nLength; i++) {
if(i) it << "\n";
it << n[i];
}
return it;
}
};
#endif
2) And this is the class I tried making array of and how I did it (it has dynamic memory allocation)
class Tune {
char* artist;
char* song;
public:
explicit Tune(const char* a, const char* s) {
artist = new char [strlen(a)+1]; strcpy(artist, a);
song = new char [strlen(s)+1]; strcpy(song, s);
}
...
#include "Array.h"
void main() {
Array<Tune> tunes(5); //Array of 5 elements
}
error C2512: 'Tune' : no appropriate default constructor available
1> c:\x\x\x\visual studio 2010\projects\x\x\array.h(26) : while
compiling class template member function 'Array<T>::Array(int)'
1> with
1> [
1> T=Tune
1> ]
1> c:\x\x\x\visual studio 2010\projects\x\x\main.cpp(10) : see reference to
class template instantiation 'Array<T>' being compiled
1> with
1> [
1> T=Tune
1> ]
3) Then I remembered that I could solve that issue with something like this (without using my array template class):
void main() {
Tune **tunes = new Tune*[5];
...
}
I would like to know is this the solution and how do I create Array of pointers using my template array class, and second (lest say I have overriden operator<<), how to I print one or all of the elements of the array.
The full program is huge, this is the piece of it. Most of the code is under comments, so the issue is isolated.
I am pretty stuck and this project means a lot to me, but I am an inexperienced programmer so I find it hard to handle issue like this. Thanks for help in advance.
Cheers!
First of all please show the full error message. Secondly it is not clear what is MyType and whether it has the default constructor.
If MyType is for example some arithmetic type then the code below will be compiled without errors.
#include "Array.h"
int main() {
Array<MyType> data(5); //Array of 5 elements
}
At least class Array has the default constructor though it is not used. As for the type MyType then it can be said nothing because you did not show neither the full error message nor the definition of MyType.
I suggest to check whether MyType has the default constructor.
If you want to create an array of pointers then you should write
Array<MyType *> data(5);
As for this code
void main() {
MyType **data = new MyType*[5];
...
}
then it has nothing common with the problem. Take into account that main shall be defined as having return type int.
EDIT: If do not take into account errors in the definition of class Tune, then it has no default constructor. So you should decide whether you want to create an array of obects of type Tune or an array of pointers to objects of type Tune. I already showed how fo define the array of pointers. Or define the default constructor for class Tune.
How do I create an array of pointers using my template Array class?
If your class needs an alternate way of constructing its elements, you should create another constructor that initializes it the way you wish, similar to std::vector's constructor:
Array( int count, const T& value );
The easiest way to implement this would be to declare m_ptData as a double pointer and initialize it like so:
Array( int count, const T& value ) : m_ptData(new T*[count])
{
for (int i = 0; i < count; ++i)
{
m_ptData[i] = new T(value);
}
}
The best (and most difficult) way would be to use placement-new to initialize it, this is how std::vector does it. You can use it like this:
int main()
{
Array<MyType> data(5, MyType("abc")); // Array of 5 elements,
// all initialized to MyType("abc")
}
How do I print one or all of the elements of the array?
The inserter operator<<() should be used to print the entire array, so making it do something like printing only some of the elements would be a bit confusing to maintainers of your code. As alternatives, you can create a stream manipulator if you wish to customize output, or you can use a member function that takes a count of the numbers you would like to print. Also, your class can have begin() and end() functions which return pointers to the beginning and end of the array, so the user of the class can implement the printing at their discretion. In either cases, looping should be used to print the elements.

Initialize array of objects from a function (C++)

How do I initialize an array of objects from a function? I'm aware the code below is impractical; I'm just teaching myself C++.
Here is a structure that contains data.
struct pointStruct {
int numberPoints;
Point2D pointArray;
};
The Point2D class has instance variables x and y. In a separate function, I have:
void setPoints(void) {
pointStruct myPointData;
myPointData.numberPoints = 4;
myPointData.pointArray[4]; // here is the problem
// loop with i
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
I'm trying to initialize the array so that I can loop through it and set the x,y coordinates. I've tried using new and some other methods but I can't work through what I need to do. How can I fix this?
When I try to compile this code, I get the error "no match for 'operator[]' in 'myPointData.pointStruct::pointArray[4]' "
You should probably use std::vector like MadScienceDreams suggests.
However, if you want to learn about such things, you could use a pointer instead. For example:
struct pointStruct {
int numberPoints;
Point2D* pointArray;
};
void setPoints(void) {
pointStruct myPointData;
const int num_points = 4;
myPointData.numberPoints = num_points;
myPointData.pointArray = new Point2D[num_points];
for(int i = 0; i < num_points; ++i) {
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
// Do stuff with myPointData...
// Don't forget to have a "delete" for every "new" when you're done.
delete[] myPointData.pointArray;
}
Point2D pointArray;
pointArray is a single instance to Point2D. It is not an array of instances in which case it's type is Point2D [N].
myPointData.pointArray[4];
The above statement calls operator [] taking a parameter of type int, which is not you actually want. Since there is no such member function in Point2D, compiler complains. If you wish to create array of instances, use std::vector<Point2D>.

Passing pointer to 2D array c++

I'm having this problem for quite a long time - I have fixed sized 2D array as a class member.
class myClass
{
public:
void getpointeM(...??????...);
double * retpointM();
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A ); ???
A = moo.retpointM(); ???
}
I'd like to pass pointer to M matrix outside. It's probably very simple, but I just can't find the proper combination of & and * etc.
Thanks for help.
double *A[3][3]; is a 2-dimensional array of double *s. You want double (*A)[3][3];
.
Then, note that A and *A and **A all have the same address, just different types.
Making a typedef can simplify things:
typedef double d3x3[3][3];
This being C++, you should pass the variable by reference, not pointer:
void getpointeM( d3x3 &matrix );
Now you don't need to use parens in type names, and the compiler makes sure you're passing an array of the correct size.
Your intent is not clear. What is getpointeM supposed to do? Return a pointer to the internal matrix (through the parameter), or return a copy of the matrix?
To return a pointer, you can do this
// Pointer-based version
...
void getpointeM(double (**p)[3][3]) { *p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(double (*&p)[3][3]) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
For retpointM the declaration would look as follows
...
double (*retpointM())[3][3] { return &M; }
...
int main() {
double (*A)[3][3];
A = moo.retpointM();
}
This is rather difficult to read though. You can make it look a lot clearer if you use a typedef-name for your array type
typedef double M3x3[3][3];
In that case the above examples will transform into
// Pointer-based version
...
void getpointeM(M3x3 **p) { *p = &M; }
...
int main() {
M3x3 *A;
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(M3x3 *&p) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
// retpointM
...
M3x3 *retpointM() { return &M; }
...
int main() {
M3x3 *A;
A = moo.retpointM();
}
The short answer is that you can get a double * to the start of the array:
public:
double * getMatrix() { return &M[0][0]; }
Outside the class, though, you can't really trivially turn the double * into another 2D array directly, at least not in a pattern that I've seen used.
You could create a 2D array in main, though (double A[3][3]) and pass that in to a getPoint method, which could copy the values into the passed-in array. That would give you a copy, which might be what you want (instead of the original, modifiable, data). Downside is that you have to copy it, of course.
class myClass
{
public:
void getpointeM(double *A[3][3])
{
//Initialize array here
}
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A );
}
You may want to take the code in your main function which works with the 2D array of doubles, and move that into myClass as a member function. Not only would you not have to deal with the difficulty of passing a pointer for that 2D array, but code external to your class would no longer need to know the details of how your class implements A, since they would now be calling a function in myClass and letting that do the work. If, say, you later decided to allow variable dimensions of A and chose to replace the array with a vector of vectors, you wouldn't need to rewrite any calling code in order for it to work.
In your main() function:
double *A[3][3];
creates a 3x3 array of double* (or pointers to doubles). In other words, 9 x 32-bit contiguous words of memory to store 9 memory pointers.
There's no need to make a copy of this array in main() unless the class is going to be destroyed, and you still want to access this information. Instead, you can simply return a pointer to the start of this member array.
If you only want to return a pointer to an internal class member, you only really need a single pointer value in main():
double *A;
But, if you're passing this pointer to a function and you need the function to update its value, you need a double pointer (which will allow the function to return the real pointer value back to the caller:
double **A;
And inside getpointM() you can simply point A to the internal member (M):
getpointeM(double** A)
{
// Updated types to make the assignment compatible
// This code will make the return argument (A) point to the
// memory location (&) of the start of the 2-dimensional array
// (M[0][0]).
*A = &(M[0][0]);
}
Make M public instead of private. Since you want to allow access to M through a pointer, M is not encapsulated anyway.
struct myClass {
myClass() {
std::fill_n(&M[0][0], sizeof M / sizeof M[0][0], 0.0);
}
double M[3][3];
};
int main() {
myClass moo;
double (*A)[3] = moo.M;
double (&R)[3][3] = moo.M;
for (int r = 0; r != 3; ++r) {
for (int c = 0; c != 3; ++c) {
cout << A[r][c] << R[r][c] << ' ';
// notice A[r][c] and R[r][c] are the exact same object
// I'm using both to show you can use A and R identically
}
}
return 0;
}
I would, in general, prefer R over A because the all of the lengths are fixed (A could potentially point to a double[10][3] if that was a requirement) and the reference will usually lead to clearer code.

Problem passing a list of objects to another class, C++

Below I have written a sample program that I have written to learn about passing a list of objects to another class. I talk about the problems I am having below.
#include <iostream>
#include <vector>
using namespace std;
class Integer_Class
{
int var;
public:
Integer_Class(const int& varin) : var(varin) {}
int get_var() { return var; }
};
class Contains_List
{
typedef Integer_Class* Integer_Class_Star;
Integer_Class_Star list;
public:
Contains_List(const Integer_Class_Star& listin) : list(listin) {}
Integer_Class* get_list() { return list; }
};
int main (int argc, char * const argv[])
{
// Create a vector to contain a list of integers.
vector<Integer_Class> list;
for(int i = 0; i < 10; i++)
{
Integer_Class temp_int(i);
list.push_back(temp_int);
}
This is where the errors start occuring. Could someone please look at the second class definition and the code below and shed some light on what I'm doing wrong. Thank you so much, as always!
// Import this list as an object into another object.
Contains_List final(list);
// Output the elements of the list by accessing it through the secondary object.
for(int i = 0; i < 10; i++)
{
cout << final.get_list()[i].get_var();
}
return 0;
}
You don't mention what sort of errors you are getting, but one very obvious problem with your code is that the constructor for Contains_List expects a pointer to Integer_Class while the parameter you are sending it (list) is of type vector<Integer_Class>.
A vector is not the same as an array, so you cannot pass it as pointer to the type it contains. Either change your constructor to accept a vector or pointer/reference to vector, or change the code that is causing you problems so that it sends it a pointer to an array.
The 'Contains_List' constructor takes in an 'Integer_Class*'
You declare 'list' to be of type 'vector', yet you pass it to the the 'Contians_List' constructor. You should change the 'Contains_List' class so that it holds a vector instead of an Integer_List array. The two are not interchangeable.
You could also change the vector to be an array of Integer_List's instead, if you so wished.