What does explicitly initializing a member mean? - c++

In the following code
class someClassB;
class someClassA
{
public:
someClassA(int x, int y);
private:
someClassB* B;
};
class someClassB
{
public:
someClassB(int x, int y);
private:
int x;
int y;
someClassA A;
};
someClassA::someClassA(int i, int j)
{
B->x = i;
B->y = j;
}
someClassB::someClassB(int i, int j)
{
x = i;
y = j;
A = new someClassA(i, j);
}
why do I get an error saying 'Constructor for 'someClassB' must explicitly initialize the member 'A' which does not have a default constructor'?
Am I not initializing 'A' in someClassB's constructor?

someClassA does not have a default constructor. Currently, someClassB needs to default initialize it, resulting in the compilation error you quote. .You need to explicitly initialize the someClassA data member using one of its available constructors. For example,
someClassB::someClassB(int i, int j) : x(i), y(j), A(i, j)
{
}
Here, x and y are also initialized in the constructor initialization list, as opposed to default initialized and then assigned values to, as in your code.
Also note that, in general, this makes no sense in C++:
A = new someClassA(i, j);
new returns a pointer.

Given that you are using A with new, I suspect you meant to declare it as a pointer:
someClassA* A;
If not, then you need to initialize it in someClassB's initializer list.

someClassA::someClassA(int i, int j)
{
B->x = i;
B->y = j;
}
create a new instance of class someClassB as B is a pointer and you didn't allocated memory for this.
A = new someClassA(i, j);
A is not a pointer this is an instance of someClassA

Related

Constructor with an object as argument (C++)

I have this class:
class CContact {
public:
CTimeStamp m_Stamp;
int m_Num1;
int m_Num2;
CContact(CTimeStamp mStamp, int i, int i1) {
m_Stamp = mStamp;
m_Num1 = i;
m_Num2 = i1;
}
};
I get the following error:
Constructor for 'CContact' must explicitly initialize the member 'm_Stamp' which does not have a default constructor
I want to be able to use it this way:
test.addContact(CContact(CTimeStamp(1, 2, 3, 4, 5, 6), 999999999, 777777777));
What does it mean, and how can I fix it?
The error is self-explantory. Your CContact constructor is not passing any values to m_Stamp's constructor, so the compiler has to default-construct m_Stamp, but it can't because CTimeStamp does not have a default constructor.
You need to initialize CContact's members (or at least m_Stamp) in the CContact constructor's member initialization list rather than in the constructor's body, eg:
CContact(CTimeStamp mStamp, int i, int i1) :
m_Stamp(mStamp),
m_Num1(i),
m_Num2(i1)
{
}
This will invoke the copy constructor for m_Stamp rather than the default constructor.
You original code was effective equivalent to this, which is why it failed:
CContact(CTimeStamp mStamp, int i, int i1)
: m_Stamp() // <-- here
{
m_Stamp = mStamp;
m_Num1 = i;
m_Num2 = i1;
}
You have to define a default constructor for class CTimeStamp. For example:
CTimeStamp(int aa=0, int bb=0, int cc=0)
:a{aa},b{bb},c{cc}{}

Initializing an array of pointers to a defined structure with constructor

struct Mystruct
{
int x;
int y;
Mystruct(int x, int y);
}
------------------------
class Myclass
{
Mystruct** p;
Myclass(int n);
}
------------------------
Myclass::Myclass(int n)
{
this->p = new Mystruct*[n];
for ( int i = 0; i < n; i++ )
this->p[i] = new Mystruct[n];
}
This will not work. I know the problem lies somewhere with default constructor not being available, but I do not know how to move forward from here.
you want
Myclass::Myclass(int n)
{
this->p = new Mystruct*[n];
for ( int i = 0; i < n; i++ )
this->p[i] = new Mystruct[n];
}
because Mystruct** p;
You also need to save the dimension, and to add a destructor, very probably the constructor must be public.
As said in a remark to be able to allocate your array of Mystruct that one need a constructor without parameter

C++ - constructor for nested non-pointer class

There is non-pointer (body) nested class in outer class.I need to call its constructor from outer class constructor after some calculations.How to do?
class nested
{
int value;
nested(int x) {value=x;};
nested() {value=0;};
};
class outer:
{
nested n;
nested *pn;
outer(int x);
};
outer::outer(int x1)
{
x = x1;
y = x + 1 *x*x;//some long calculations needed for nested
pn = new nested(y); //this is trivial
n = nested(y); //??? how to initialize non-pointer class?????
}
One solution would be to calculate y and store it as a member variable. That way you can calculate and cache it before initializing anything that depends on it.
class outer
{
public:
outer(int x)
, y(CalculateY(x))
, n(y)
, pn(new nested(y))
{}
private:
int CalculateY(int x); // this can be static
int y;
nested n;
nested *pn;
};
Note
int y must be declared before anything that relies on it since member variables are initialized in the order they're declared in.

Invalid types ‘<unresolved overloaded function type>[int]’ for array subscript - C++

I've this error when I try to save a number into my vector...
Invalid types ‘<unresolved overloaded function type>[int]’ for array subscript
The code is:
class Elemento{
private:
int Nodo;
public:
Elemento(){};
~Elemento(){};
void SetNumero(int x) { Nodo = x; };
int GetNumero() { return Nodo; };
};
class MagicSquare{
private:
int N;
int Possibili_N;
int Magic_Constant;
vector<Elemento> Square(int Possibili_N);
public:
MagicSquare() { };
~MagicSquare() { };
void Set_N(int x) { N = x; };
void Set_PossibiliN(int x) { Possibili_N = x; };
void Set_MagicConstant(int x) { Magic_Constant = x; };
. . .
void SetSquare(int i, int x) { Square[i].SetNumero(x); }; // got error here
int GetSquare(int i) { return Square[i].GetNumero(); }; // got error here
};
I've got error whenever I use Square[i].method()...
I call a method that pass the index in the Square and the value to put in Elemento->Nodo, but I've to use a public method to access to private Nodo. The same with the GET. I want to get the value for displaying it.
You seem to have declared Square as a function, not a variable.
Instead, declare vector<Elemento> Square; and initialize it in the constructor.
You declared Square as a function, not a variable. So Square[i] is not valid.
Change
vector<Elemento> Square(int Possibili_N);
to
vector<Elemento> Square;
or call it using
Square(i)
if it is actually a function.
If you change it to a variable, you need to be sure to initialize it properly, preferably in the constructor.
Your line vector<Elemento> Square(int Possibili_N); is know as C++ most vexing parse.
Instead of declaring a member variable, as intended, you are declaring a function taking an int and returning a vector.
Instead, setup the member vector (and all other member variables) in the constructor initialization list:
class MagicSquare{
private:
int N;
int Possibili_N;
int Magic_Constant;
vector<Elemento> Square;
public:
MagicSquare( int n, int p, int m ) :
N( n ),
Possibili_N( p ),
Magic_Constant( m ),
Square( p ) {
}
...

Pointer to object arrays as members overwrite memory

Here is the deal. We have 2 different classes Class F and Class O
class F {
private:
int x;
int y;
public:
int getXf(){ return x; }
int getYf(){ return y; }
f(int ,int);
};
class O {
private:
int n;
int k;
int x;
int y;
char type;
int id;
int t;
public:
O(int ,int ,int ,int ,int);
int getX(){ return x; }
int getY(){ return y; }
};
And we have a third class P, where we initialize the values. In the class we are creating the two arrays of objects.
class Prog {
public:
int count;
int fcount;
O *o[]; //here we are declaring the arrays of objects
F *f[];
public :
//void init(); Here is the function where we initializing the values
};
Now the 2 for statements where we are creating the objects.
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o[i] = new O(100,50,i,randx,randy);
}
for(int i=0;i<3;i++){
randx = rand() % 10;
randy = rand() % 10;
f[i] = new F(randx, randy);
}
When we are printing all of the objects are here but the first 3 of the first class are replaced by the objects of the seconds. Exactly the 100 and 50 (1st for) from randx and randy (2nd for) respectively.
O *o[];
This declares an array of unknown size, which is an incomplete type. C++ doesn't allow that to be used as a class member, although some compilers will allow it as an extension, interpreting it as an array of zero size. In either case, it's not what you want.
If you know the array bound at compile time, then you should specify it:
O *o[10];
otherwise, you'll need to dynamically allocate an array at run time:
std::vector<O*> o;
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o.push_back(new O(100,50,i,randx,randy));
}
I would also suggest storing objects, or possibly smart pointers, rather than raw pointers in the array. If you really do want raw pointers for some reason, then remember to delete the objects once you've finished with them since that won't happen automatically, and don't forget the Rule of Three.
You are declaring arrays, but you never allocate memory for them. What you are seeing is just how your code is walking all over the stack.
Something more appropriate:
struct X {}; struct Y {};
class P {
public:
P() : xs(new X*[10]), ys(new Y*[10]) { init(); }
~P() {
// delete all objects
for(std::size_t i = 0; i < 10; ++i)
delete xs[i];
for(std::size_t i = 0; i < 10; ++i)
delete ys[i];
delete[] xs;
delete[] ys;
}
private:
void init() {
// initialize
for(std::size_t i = 0; i < 10; ++i)
xs[i] = new X();
for(std::size_t i = 0; i < 10; ++i)
ys[i] = new Y();
}
// prevent assignment and copy
P& operator=(const P& other);
P(const P&);
X** xs;
Y** ys;
};
Of course, all this magic becomes unnecessary if you just use
std::vector to store your data.
The problem is due to the way you declare your arrays:
O *o[/*No size here*/];
F *f[/*No size here*/];
Since you do not state the size of the arrays, this is equivalent to
O **o;
F **f;
Hence, you are declaring two members of types "pointer to pointer to O" and "pointer to pointer to F" respectively, but these are uninitialized and you have not allocated any memory for them to point to. That is, you actually don't have any arrays, just pointers which could be used to refer to the type of array you want.
If you know at compile time what size you want to use, you should specify that size in the declaration, which will give you a properly allocated array of that size. Otherwise, consider using an std::vector.