I wrote the following employee class:
#include<iostream>
#include<string>
using namespace std;
class employee
{
private:
int id;
int salaries[12];
int annualS;
string name;
public:
employee(int id2, string name2, int array[12])
{
id = id2;
name=name2;
salaries = array; //here where the error occurred.
}
~employee()
{
cout<<"Object Destructed";
}
employee()
{
id = 0;
name="Mhammad";
}
int annulalSalary()
{
for( int i=0; i<12; i++)
{
annualS+=salaries[i];
}
return annualS;
}
int tax()
{
return (annualS*10/100);
}
};
void main()
{
int salaries[12];
for(int i=0; i<12; i++)
{
cin>>salaries[i];
}
employee Mohammad(10,"Mohammad",salaries);
cout<< Mohammad.annulalSalary();
cout<< Mohammad.tax();
}
...but when I compile it the, compiler returns the following error:
cannot convert from 'int []' to 'int [12]'
Could anyone help me solve this problem?
you can not copy an entire array just using = operator in c++. you have two options.
overload = operator
or
use a for loop like this to copy each element of one array to another
for(int i=0 ; i<12 ; i++)
salaries[i]=array[i];
on a different note don't use magic numbers like 12 in your code.
Instead of a C array, use the C++ std::array<>, like this:
class employee {
//...
std::array<int, 12> salaries;
//...
};
and of course you'd have to include <array> too. And declare the constructor like this:
employee(int id2, string name2, std::array<int, 12> const & array)
{
//...
}
(or drop the const & if you're not sure what they are or don't need them.)
You can not copy arrays by assignment. You need to copy each element individually. Use std::copy.
std::copy(array, array+12, salaries);
Or use std::vector<int> or std::array<int, 12> as suggested by Borgleader which does copy by assignment.
Use the vector class!
But to solve your problem :
int salaries[12] should be int* salaries
employee(int id2, string name2, int array[12]) should be employee(int id2, string name2, int* array)
but then you might a problems of referencing things outside the allocated memory and segfault.
USE VECTORS!
Related
Code-1
#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s)
{
for(int i=0; i<=4; i++)
{
p[i]=*q;
q++;
}
strcpy(str,s);
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);
return 0;
}
Output ( Runs smoothly but just gives warning )
Clang-Tidy: Constructor does not initialize
these fields: p, str
Why this warning is coming. I know that I am assigning in constructor not initializing but When I create simple class which just have int type variable and If I assign that in this same way it didn't give such warning ?
Code-2
#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s): // just not getting how we can do this initialization
{
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);
return 0;
}
Is there any way to initialize int type or C-style char array via member initialization list through constructor.
I know that I can replace char array with string but I want to know a way for C-style char array.
Arrays in C++ are not the friendliest bit of the language.
Specialy not when you let them decay to pointers (size information is lost).
So I prefer to use std::array, std::vector and std::string since these standard library classes help you prevent all sort of memory bugs.
About your initialization question, yes you can only assign in the body of the constructor. This is another reason I like std::array/std::vector better you can use them in the initializer. I also consider ::strcpy to be a left over from 'C' not to be used anymore in current C++. Have fun learning more C++ :)
#include <iostream>
//#include <cstring> // <== don't use this. (If you want to use strings in C++ use <string>
#include <vector>
#include <string>
// try to learn not to use what is called
// "magic numbers" in your source code!
// define numbers you are going to use
//
const std::size_t int_array_size = 5;
const std::size_t string_array_size = 20;
// we don't know the length of the string yet, but we can let
// the compiler figure it out and we make a templated constructor
class A
{
public:
// pass arrays in by const, you're not supposed to
// change their content.
A(const int (&p)[int_array_size], const char (&str)[string_array_size])
{
// I always use std::size_t for indices in arrays (not supposed to be <0)
for (/*int*/ std::size_t i = 0; i < int_array_size; i++) m_p[i] = p[i];
// don't use ::strcpy it's not "safe". It depends on correct input
// like the string having a trailing 0
for (std::size_t i = 0; i < string_array_size; i++) m_str[i] = str[i];
}
private:
int m_p[int_array_size];
char m_str[string_array_size];
};
// this is one way I would code it.
// using C++ with variable length array (so I use std::vector, for fixed length use std::array)
class B
{
public:
B(const std::vector<int>& p, const std::string& str) :
m_p{ p },
m_str{ str }
{
}
private:
std::vector<int> m_p; // or std::array<int,int_array_size>
std::string m_str;
};
int main()
{
// I prefer to use aggregate initialization (https://en.cppreference.com/w/cpp/language/aggregate_initialization)
int r[int_array_size]{ 2, 3, 5, 7, 11 };
// The next line is defined behavior. C++ standard says all remaining
// values of ch after bonaparte will be 0
char ch[string_array_size]{ "bonaparte" };
A a1(r, ch);
B b1{ {1,2,3}, "hello world!" };
return 0;
}
I am working on some pointer practice in my C++ class and have gotten stuck working on problem, say I have a class like this :
class foo
{
public:
foo(char *inputWord = ""); // Default parameter constructor
private:
char * word;
int wordSize; // length of word
};
and in main I have :
int main()
{
foo baz("t");
foo bar("test");
return 0;
}
How would I make an implementation for this constructor?
So far I know that to initialize wordSize I could just do :
foo::foo()
{
wordSize = strlen(inputWord);
}
But I don't understand how to initialize the char *word.
I've tried the following:
strcpy(word,strlen);
for(int i =0; i< wordSize; i++)
word[i] = inputWord[i];
int count = 0;
while(count < wordSize+1)
{
inputWord = word;
inputWord++;
}
None of the above methods work. I even tried using memcpy() and memmove() but I just got stuck.
Has anyone dealt with this before and could point me in the right direction?
You can simply use strcpy just after having allocate memory:
Foo(char *inputWord) {
if (inputWord==nullptr) { // manage null pointer
wordSize=0;
word=nullptr;
return;
}
wordSize = strlen(inputWord); // store string length
word = new char[wordSize+1]; // allocate enough memory to store the original C-style string
strcpy(word,inputWord); // copy the original into destination
}
This is C-style, but you'd better use strings in C++:
class Foo {
private:
string word;
public:
Foo(const string &input) : word(input) {} // initialize word with inputWord (let C++ string type do all the tricky parts)
};
C++ string type is able to manage correctly (de)allocations, length, etc.
I am confused about this library code..
what is the purpose of writing pointer in attributes name?
Like string *name;
this is the code:
#include <iostream>
using namespace std;
class stringlist
{
private:
int numstrings;
string *strings;
public:
stringlist() : numstrings(0), strings(NULL)
{}
// copy constructor
stringlist(const stringlist &other) :
numstrings(other.numstrings),
strings(new string[other.numstrings]) {
for (int i=0; i<numstrings; i++) {
strings[i] = other.strings[i];
}
}
// destructor
~stringlist() {
if (numstrings > 0) delete [] strings;
}
void printStrings();
const string& getString(int num);
void setString(int num,
const char *astring);
void setString(int num,
const string &astring);
int getNumstrings() {
return numstrings;
}
void setNumstrings(int num);
void swapStrings(stringlist &other) ;
// overloaded operators
stringlist& operator =
(const stringlist &other) {
stringlist temp(other);
swapStrings(temp);
return *this;
}
};
Can anyone please explain what is the purpose of
using string *strings
instead of string strings?
Thanks all!
string *strings;
declares a pointer to the first element of an array of strings. Because of C/C++ array/pointer semantics, you can treat this as an array of strings, e.g. index it as strings[n] to get the nth element.
string strings;
would just be one string. Since the class is for holding a list of strings, declaring just one string would not be sufficient.
In the code you gave, *strings is used for a dynamic array.
You can see that it's allocated with strings(new string[other.numstrings]) and the destructor deletes it if it's pointing to something.
More on dynamic arrays:
- http://www.cplusplus.com/doc/tutorial/dynamic/
Static array vs. dynamic array in C++
I have a class with member of dynamic array (I posted my code in pastebin) I wonder if my both classes are correct and if there is anything wrong with them? Also how I need to write (41 line) a function that sets class Student to StudentsDynamicArray?
Here is my array class
class StudentsDynamicArray{
private:
Student *Stud;// students dynamic array
int n; // current size of array
int nmax; // max size of array
public:
StudentsDynamicArray():n(0), Stud(NULL), nmax(0){}
StudentsDynamicArray(int n):
n(n){}
~StudentsDynamicArray(); // destructor
void SetStud(Student S){Stud[n++] = S;} // I get error when I try to set String or Int. //How I need to change this?
Student GetStud(int i){return Stud[i];}
void IncreaseSize(int ns);
};
//Function which change size of array
void Student::ChangeSize(int kiek){
if(kiek > nmax){
int *SNEW = new int[kiek];
for(int i=0; i<n; i++)
SNEW[i] = mark[i];
delete [] mark;
mark = SNEW;
nmax = kiek;
}
else if(kiek < nmax){
int *SNEW = new int[kiek];
for(int i=0; i<n; i++)
SNEW[i] = mark[i];
delete [] mark;
mark = SNEW;
n = nmax = kiek;
}
}
In Student class you have
int *mark
this is indication that you must apply rule of three: copy constructor, assignment operator and destructor. First two should make a copy of dynamic array, and destructor should free memory. You have only destructor properly implemented. The same applies to StudentsDynamicArray class.
as for:
void SetStud(Student S){Stud[n++] = S;}
from your code it looks like you have not called IncreaseSize initially, and Stud is possibly NULL once you call SetStud. You can fix it by calling it in constructor:
StudentsDynamicArray():n(0), Stud(NULL), nmax(0){ IncreaseSize(10); }
also, all of the above would not be necessary if you would use std::vector, so if such low lever dynamic arrays are not your requirement then use std::vector. Then you would use rule of zero.
[edit]
Your copy constructor / assignment operators should like as follows:
Student (const Student& other) {
// here allocate this->mark to be the same size as in other
// copy values from other.mark to this->mark
// also copy other values from `other` to this
}
Student& operator= (const Student& other)
{
// here allocate this->mark to be the same size as in other
// copy values from other.mark to this->mark
// also copy other values from `other` to this
return *this;
}
As you can see they are "quite" similar. Wiki on rule of three is actually updated to C++11, where you can add move semantics which increase efficiency of copy by value operations (and actually are known as rule of five). If you are learning basics, you can stay with previous rules.
You could better use std::vector to wrap the students into a collection. This will dramatically increase performance, and will lead to less errors.
Below is the prototype of classes you can use.
class Student
{
private:
string mName;
unsigned int mAge;
public:
Student() : mName(""), mAge(0) {}
Student( string name, unsigned int age ) : mName(name), mAge(age) {}
string get_name() const;
void set_name( string name );
unsigned int get_age() const;
void set_age( unsigned int age );
};
class Students
{
private:
vector<Student> mCollection;
public:
Students() : mCollection() { }
Students( vector<Student> &input_collection ) : mCollection( input_collection ) { }
Students &add_student( Student &s );
Students &remove_student( Student &s );
Students &remove_student( string name );
Students &remove_student( size_t index );
Students &edit_student( size_t index, string new_name, unsigned int new_age );
};
Hope this helps.
I've just tried:
class Test
{
public:
int iArray[][];
}
...is this not possible? Do I have to set a constant value?
like:
class Test
{
public:
const int iArray[5][4];
}
I want to define [x][y] later, just have the placements there. Else it wouldn't be "dynamic" and I don't want to use a vector because I want to be able to access the values by "X" and "Y".
I think better way to achieve this is to use pointers. You can do like this.
#include <cstdlib>
#include <iostream>
using namespace std;
class PointerTest {
private:
int** array;
int x, y;
public :
void setValue(int row, int col,int value);
int getValue(int row, int col);
PointerTest(int row, int col);
~PointerTest() {
for(int i=0;i<x;i++) {
delete array[y];
}
}
};
PointerTest::PointerTest(int row, int col) {
x=row, y=col;
for(int i=0;i<row;i++) {
*array=new int[col];
}
}
void PointerTest::setValue(int row, int col, int value) {
*(array[row])=value;
}
int PointerTest::getValue(int row, int col) {
return *(array[row]);
}
int main(int argc, char *argv[])
{
PointerTest* t=new PointerTest(4,5);
t->setValue(0,0,464);
cout<<"The value in array: "<<t->getValue(0,0)<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
What about
tempalte <int N1, int N2> class Test
{
public:
int iArray[N1][N2];
};
?
What about putting a std::vector in a vector?
std::vector< std::vector< const int > > iArray;
There aren't many reason to use "plain" arrays in C++.
If you want to decide int iArray[][]; size later then you can use vector< vector<int> > iArray;.
The other way is to use nested new[], which would be little complex.
No this is not possible. But you can have a pointer in your class like
int **ptr;
and then in the constructor or where ever allocate the memory for your array with
ptr = (int **)malloc( the size you want );
or with the "new[]"-operator in C++.
but if you are using C++ .. the best way is to use:
std::vector< std::vector< int >> array;
class Test
{
public:
Test()
{
iArray = new int*[5];
for(int i = 0; i < 5; i++)
iArray[i] = new int[4];
}
~Test()
{
for(int i = 0; i < 5; i++)
delete[] iArray[i];
delete[] iArray;
}
int** iArray;
};
Will allow you to allocate a 2d int array at runtime (in this example it is a 5x4), but in all honestly I would use vectors as pointed out by some other posters, you don't need to worry about freeing the memory afterwards like you do with the use of new.