I wanted to design a composition using C++ as shown below:
#define NUMBER (4)
class wheel {
int radius;
public:
wheel();
wheel(int);
//copy constructors prototype
//getters and setters prototypes
};
wheel::wheel() : radius(1) {}
wheel::wheel(int r) : radius(r) {}
//wheel class copy constructor definition
//wheel class setter and getter definitions
class car {
wheel fourwheels[NUMBER];
public:
car();
};
car::car() {
fourwheels[NUMBER] = {wheel(1), wheel(1), wheel(1), wheel(1)}; //error code
//wheel fourwheels[NUMBER] = {wheel(1), wheel(1), wheel(1), wheel(1)}; //non-error code
}
int main() {
car mycar;
return 0;
}
While compiling the code, I am getting the following error:
error: no match for 'operator=' (operand types are 'wheel' and '<brace-enclosed initializer list>')
Queries:
Why does this error occur ??
When I comment the error code line and uncomment the non-error code line, it works fine. Why do we have to add the type wheel for the array definition?
You are attempting to assign to an array element. And one that's out of range at that.
Using the constructor's initializer list, this will compile, though you should consider using STL containers rather than a raw array.
car::car() : fourwheels{wheel(1), wheel(1), wheel(1), wheel(1)}
{
}
The code you had commented out "worked" because it declared and initialized a new array of four wheels.
Since the default constructor for wheel provides a radius of 1, you could also write:
car::car() : fourwheels{wheel(), wheel(), wheel(), wheel()}
{
}
But, if we used std::array to hold our wheels, we can simplify this further, as the elements of fourwheels will be initialized using the wheel type's default constructor, which we don't have to write.
class car {
std::array<wheel, NUMBER> fourwheels;
};
Why does this error occur ??
Raw arrays are not copy-assignable. That is, the following will not work:
int nums[4] = {};
nums = {1, 2, 3, 4};
That is essentially what you're trying to do in your car constructor. Instead, you need to initialize the fourwheels member in the member initialization list:
car::car()
: fourwheels{wheel(1), wheel(1), wheel(1), wheel(1)}
{}
When I comment the error code line and uncomment the non-error code line, it works fine. Why do we have to add the type wheel for the array definition ??
Because you're not initializing your car class's member there. You're declaring and initializing a different array, also named fourwheels that is local to the constructor body. The class member remains default-initialized.
Related
I want to initialize an array of pointers the nice way.. Something like
handler[numberOfIndexes] = {&bla, &ble, &bli, &blo , &blu};
But it doens't work this way. I get an error, obviously, because I'm trying to place an array of pointers to functions, in a single pointer to function:
cannot convert ‘<brace-enclosed initializer list>’ to ‘void (A::*)()’ in assignment
So, here's the code for you to test:
#include <iostream>
#include <list>
using namespace std;
class A
{
private:
void first();
void second();
void third ();
// and so on
void(A::*handlers[4])(void);
public:
A();
};
void A::first()
{
}
void A::second()
{
}
void A::third()
{
}
A::A()
{
//this is ugly
handlers[0] = &A::first;
handlers[1] = &A::second;
handlers[2] = &A::third;
//this would be nice
handlers[4] = {&A::first,&A::second,&A::third,0};//in static this would work, because it would be like redeclaration, with the type speficier behind
}
int main()
{
A sup;
return 0;
}
UPDATE:
In Qt this doesn't work.
I get :
syntax error: missing ';' before '}'
And if I change to
A::A() : handlers ({&A::first, &A::second, &A::third, 0})//notice the parentheses
then a this happens
Syntax Error: missing ')' before '{'
Warning: The elements of the array "A :: Handlers" are by default "initialized.
So, what's the problem with Qt?
By this point, you should have understood what I want to do. Just do a nice initialization of the array of pointers.
Thank you.
Just use an actual initialization, not an assignment (arrays cannot be assigned to).
A::A() : handlers {&A::first, &A::second, &A::third, 0} {}
I'm making a monopoly game, and I have two arrays of Vectors for coordinates for my 2d array of characters. Below is my board.h where the array is kept in the board class
class Board {
...
Vector propList[40];
Vector coordList[40];
...
public:
...
};
I am getting an error running my program in bash when trying to create the executable, displayed below (there are 2 identical errors for each array)
board.cc:15:8: error: constructor for 'Board' must explicitly initialize the member 'propList' which does not have a default constructor
Board::Board() {
^
./board.h:17:12: note: member is declared here
Vector propList[40];
I have all 40 elements initialized in my board constructor as displayed below
propList[0] = Vector(-1, -1);
propList[1] = Vector(73, 51);
...
propList[39] = Vector(81, 46);
coordList[0] = Vector(81, 54);
coordList[1] = Vector(73, 54);
...
I also tried the following
Vector v = (-1, 1);
propList[0] = v;
...
and receive the same error. Does anybody know what is going on and how to fix it?
edit: I forgot to add my vector code. I had to create a constructor since I can't use C++11 initialization on my computer.
vector.cc
#include "vector.h"
Vector::Vector(int x, int y) : x(x), y(y) {}
vector.h
struct Vector {
Vector(int x, int y);
int x;
int y;
};
In your constructor, these are assignments, not initialization. Constructors have an initialization list specifically for this purpose. Unfortunately, you can't initialize arrays like this.
Here's the initialization list for a simple int member:
class MyClass
{
int myField;
MyClass() :
m_myField(1)// initialization
{
// right here, myField is 1.
myField = 2;// assignment.
}
};
This initializes myField to 1. Then assigns 2, like you're doing in your constructor.
You can't initialize arrays like this, so I would recommend a workaround: A std::vector of Vectors. Yea that's confusing because both are called "vector", but they mean different things. std::vector is a storage container.
std::vector<Vector> propList;
and in your constructor, add Vector objects to the propList
Board::Board()
{
propList.push_back(Vector(-1, -1));
propList.push_back(Vector(73, 51));
...
}
Another solution is to add a default constructor to Vector. But that's a bit dirty compared to using std::vector<>.
In C++11 it may be possible using aggregate initialization in a constructor initialization list. No, it's not possible, period.
I want to use a two dimensional array of constant size as a class member in C++. I have problems initializing it in the constructor though.
Here are my non-working tries:
1.)
class A {
public:
int a[2][2];
A();
};
A::A() {
a = {{1,2},{2,4}};
}
yields: error: assigning to an array from an initializer list
2.)
class A {
public:
int a[2][2];
A();
};
A::A() {
int b[2][2] = {{1,2},{2,4}};
a = b;
}
yields: invalid array assignment
3.)
class A {
public:
int **a;
A();
};
A::A() {
int b[2][2] = {{1,2},{2,4}};
a = b;
}
yields: cannot convert ‘int [2][2]’ to ‘int**’ in assignment
I come from C background. I know that I could use std::vector and I am aware of the disadvantages this approach has but since this is an exercise for me I would like to know how to get it working with plain arrays. I should add that I want to work on this array later on. I want to change the stored values but not the size. Maybe that matters as well (I figured a const at the right place could help somehow?).
If you have C++11, you can use this syntax in the constructor definition:
A() : a{{1,2}, {3, 4}} {}
If you don't have C++11, you will need to stick to the wicked old ways:
A() {
a[0][0] = 1;
// etc
}
The first example also uses the constructor init-list, which should always be used to initialize members instead of intializing them in the constructor body.
various multidimensional array in constructor by example:
// int array1[1];
A() : array1{0} {}
// int array2[2][2];
A() : array2{{0}} {}
// int array3[3][3][3];
A() : array3{{{0}}} {}
Try this, it works for bidimensional array (in standard C++):
class A {
public:
int a[2][2];
A();
};
typedef struct{ int a[4]; } array_t;
A::A() {
int at[2][2] = {{1,2},{2,4}};
*(array_t*)a = *(array_t*)at;
}
Ciao
Angelo
Your first variant is extremely close to the right C++11 syntax:
A::A()
: a{{1,2},{2,4}}
{
}
To complement the previous answers (you guys are so fast):
What you were trying to do in case 1 and 2 is array assignment, not permitted, as compiler says ;
But I would like to draw your attention to your third case, that's a grave misconception, specially coming from C as you say.
Assigning to a a pointer to a local variable?
I am trying to initialize my MedList but it's not working. Here's what I'm talking about:
repository.h
#include "../domain/farmacy.h"
#include "../utils/DynamicVector.h"
class Repository{
private:
DynamicVector<Medicine>* MedList; //I made it pointer so it can be dynamic
public:
Repository(); //constructor
repository.cpp
#include "../domain/farmacy.h"
#include "repository.h"
#include "../utils/DynamicVector.h"
#include <stdlib.h>
Repository::Repository(){
this->MedList=new DynamicVector<Medicine>::DynamicVector(); //error
}
DynamicVector.h
template <typename Element> //this is the Dynamic Vector constructor
DynamicVector<Element>::DynamicVector()
{
this->cap=10;
this->len=0;
this->elems=new Element[this->cap];
}
the error above is:
Multiple markers at this line
- no match for 'operator=' in '((Repository*)this)->Repository::MedList = (int*)operator
new(4u)'
- expected type-specifier
- candidate is:
- expected ';'
this is the medicine class
class Medicine{
private:
int ID;
std::string nume;
double concentratie;
int cantitate;
The Dynamic Vector class:
template <typename Element>
class DynamicVector{
private:
Element* elems;
int cap;
int len;
void resize();
void CopyToThis(const DynamicVector& v);
public:
DynamicVector(); //constructor implicit
DynamicVector(const DynamicVector& ); //constructor de copiere
DynamicVector& operator=(const DynamicVector& );
~DynamicVector();
void addElement(Element elem);
Element delElementAtPosition(int pos);
Element getElementAtPosition(int pos);
int getLen();
};
What am I doing wrong? I tried a lot of variants but nothing seems to work. Could you help me?
I think you're confusing c++ syntax for creating object with some other language, e.g. Java or C#.
In c++, a constructor is called simply by declaring the variable:
DynamicVector<Element> medList; // Calls DynamicVector<Element>::DynamicVector()
The new operator in C#, is to dynamically allocate space for a variable, and returns a pointer to the allocated space. To use it here, you'd have to declare Repository::MedList as a pointer type, and initialize it like so:
DynamicVector<Medicine>* MedList; // in repository.h
this->MedList = new DynamicVector<Medicine>(); // in repository.cpp
However, as Andy Prowl pointed out, it is much better to just let the compiler do the memory management for you. To do so, you should completely remove the erroneous line in repository.cpp. Why? Well, when the repository is constructed, the compiler also tries to construct all member objects using their default constructors. This is exactly what you want, so there is no reason to try to alter the compiler's behavior.
Constructor should be:
Repository::Repository(){
this->MedList=new DynamicVector<Medicine>;
}
DynamicVector() calls the constructor for DynamicVector.
DynamicVector::DynamicVector() is a pointer to the address of the constructor function
The chances are your C++ version doesn't allow empty () for constructors.
this->MedList=new DynamicVector<Medicine>::DynamicVector(); //error
should be
this->MedList=new DynamicVector<Medicine>::DynamicVector;
or (The usual way of writing it)
this->MedList=new DynamicVector<Medicine>;
See here for more info.
EDIT. Make sure you have declared the dynamicVector constructor in the class.
Default constructor with empty brackets
Do the parentheses after the type name make a difference with new?
I have a specific situation where I've got an object that I want to use the boost random number generators on, and it has lead to a greater question which I cannot seem to answer. Here is the example code of what I'm trying to produce.
First, my header:
Class MyObject {
protected:
double some variable;
boost::random::mt19937 rgenerator;
boost::uniform_real<double> dist_0_1;
boost::variate_generator< boost::mt19937&, boost::uniform_real<double> > rand01
}
Now what I want to do is:
Class MyObject {
protected:
double some variable;
boost::random::mt19937 rgenerator(std::time(0)); //initialize to a "random" seed
boost::uniform_real<double> dist_0_1(0,1); //set the distribution to 0-1
boost::variate_generator< boost::mt19937&, boost::uniform_real<double> > rand01(rgenerator, dist_0_1);//tell it to use the above two objects
}
But this doesn't work because it is in a header. I thought I could use the constructor of MyObject to somehow call the constructors on the various sub-objects (distribution, generator, but I can't figure out how. By the time the constructor of MyObject is called, the sub-objects' default constructors have already been called, and I haven't found that they have member methods to reset these properties... besides which, that isn't the point where I am confused. Now maybe there are too many things going on and I'm confusing issues, but as far as I can tell, my problem reduces to this following, childish example:
Class Tree {
Tree();
Tree(int);
protected:
fruit apples(int);
}
Tree::Tree() {
apples(0); //won't work because we can't call the constructor again?
}
Tree::Tree(int fruit_num) {
apples(fruit_num); //won't work because we can't call the constructor again?
}
Class Fruit {
public:
Fruit();
Fruit(int);
protected:
int number_of_fruit;
}
Fruit::Fruit() {
number_of_fruit = 0;
}
Fruit::Fruit(int number) {
number_of_fruit = number;
}
I'm sure this is second nature to everyone else out there, but I can't find an article that talks about the best practice for initializing member objects of an object to a non-default constructor value.
What you want is an initializer list. For example:
Tree::Tree(int fruit_num)
: apples(fruit_num) // Initializes "apple" with "fruit_num"
{
}
You simply add a colon (:) after the constructor parameters and before the opening brace {. You can separate different member constructors with commas (,). Example:
Tree::Tree(int fruit1, int fruit2) : apples(fruit1), bananas(fruit2) {
}
The answer to this question is relatively straightforwards. You use initializer lists.
Here's an example:
class MyClass {
private:
SomeOtherType sot;
public:
MyClass() : sot(parametersForConstructorOfSOT) {}
};
You can extend this to multiple member objects, of course; it can also be used to call the constructor of a parent class to initialize private entries in a parent class if you need to do something like that.
You're so close! Just use the initialiser list syntax:
Tree::Tree() : apples(0) {
// ...
}
Tree::Tree(int fruit_num) : apples(fruit_num) {
// ...
}