Constructor of class of an array - c++

i am getting error in this code
class business
{
public:
business(); // Default Constructor
business(string busines,int r)
{
busines=busines;
ratings=r;
} // constructor;
private:
string busines;
int ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
int main(int argc, char *argv[])
{
business b[10];
b[b_count](busines,rating);
return 0;
}
It gives me the following error (http://ideone.com/FfajNS):
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:32:32: error: no match for call to ‘(business) (std::string&, int&)’

You're attempting to call a constructor on an already constructed object ... the default constructor was called during the array creation, therefore you cannot "construct" the object again. For your application, you may want to look into using a std::vector where you can create a array-like container using an object initialized from a set of default arguments.
For instance, you could do:
std::vector<business> array(10, business(business_string, rating));

I believe you want something like this:
b[2] = business("Denny's", 50);
This creates a temporary business variable by calling the constructor with the given parameters. The temporary is then copied into slot 3 of the array b.

The array b already created 10 business objects using the default constructor of that class. You can access those objects by business someBusiness = b[someIndex];
edit:
If you want to set the values of your individual objects, simply do this (notice, that you don't create these objects, just set their values):
for(int i=0; i<10; i++)
{
b[i].busines = ...;
b[i].ratings = ...;
/* or to create new ones */
b[i] = business("asd", 10);
}
It would be even better, if you stored these objects in vector, like Jason suggested

business b[10];
You create 10 "default" business object. What is b_count? I hope some int from 0 to 9.
But here you are "calling" a business object with 2 arguments:
b[b_count](busines,rating);
But business have no operator()() defined with 2 parametr.
EDIT:
You definitely have to use std::vector and carefully read the other answers.
But I know that on occasion beginners are not allowed to use the STL library, and anyway it seems that you should understand how constructors are used and how the elements of an array are initialized. Please read about static members and how they are defined and try to understand how the following example works.
#include <string>
using std::string;
class business
{
public:
business() // Default Constructor
:busines(def_busines),ratings(def_ratings){};
business(const string& bus,int r) // constructor;
:busines(bus),ratings(r){}
static void SetDef(const string& busines,int r)
{
def_busines=busines;
def_ratings=r;
}
private:
string busines;
int ratings;
static string def_busines;
static int def_ratings;
int items_owned;
int business_cancellation;
int biz_size_of_building;
int biz_shipping_method;
};
string business::def_busines=""; // Set here the default-defaults
int business::def_ratings=1;
int main(int argc, char *argv[])
{
business::SetDef("Some business",2);
business a[10];
business::SetDef("Other business",3);
business b[10];
business c("Third business",4);
return 0;
}

Related

Trouble implementing min Heaps in C++

I'm trying to implement a minheap in C++. However the following code keeps eliciting errors such as :
heap.cpp:24:4: error: cannot convert 'complex int' to 'int' in assignment
l=2i;
^
heap.cpp:25:4: error: cannot convert 'complex int' to 'int' in assignment
r=2i+1;
^
heap.cpp: In member function 'int Heap::main()':
heap.cpp:47:16: error: no matching function for call to 'Heap::heapify(int [11], int&)'
heapify(a,i);
^
heap.cpp:47:16: note: candidate is:
heap.cpp:21:5: note: int Heap::heapify(int)
int heapify(int i) //i is the parent index, a[] is the heap array
^
heap.cpp:21:5: note: candidate expects 1 argument, 2 provided
make: * [heap] Error 1
#include <iostream>
using namespace std;
#define HEAPSIZE 10
class Heap
{
int a[HEAPSIZE+1];
Heap()
{
for (j=1;j<(HEAPISZE+1);j++)
{
cin>>a[j];
cout<<"\n";
}
}
int heapify(int i) //i is the parent index, a[] is the heap array
{
int l,r,smallest,temp;
l=2i;
r=2i+1;
if (l<11 && a[l]<a[i])
smallest=l;
else
smallest=i;
if (r<11 && a[r]<a[smallest])
smallest=r;
if (smallest != i)
{
temp = a[smallest];
a[smallest] = a[i];
a[i]=temp;
heapify(smallest);
}
}
int main()
{
int i;
for (i=1;i<=HEAPSIZE;i++)
{
heapify(a,i);
}
}
}
Ultimately, the problem with this code is that it was written by someone who skipped chapters 1, 2 and 3 of "C++ for Beginners". Lets start with some basics.
#include <iostream>
using namespace std;
#define HEAPSIZE 10
Here, we have included the C++ header for I/O (input output). A fine start. Then, we have issued a directive that says "Put everything that is in namespace std into the global namespace". This saves you some typing, but means that all of the thousands of things that were carefully compartmentalized into std:: can now conflict with names you want to use in your code. This is A Bad Thing(TM). Try to avoid doing it.
Then we went ahead and used a C-ism, a #define. There are times when you'll still need to do this in C++, but it's better to avoid it. We'll come back to this.
The next problem, at least in the code you posted, is a misunderstanding of the C++ class.
The 'C' language that C++ is based on has the concept of a struct for describing a collection of data items.
struct
{
int id;
char name[64];
double wage;
};
It's important to notice the syntax - the trailing ';'. This is because you can describe a struct and declare variables of it's type at the same time.
struct { int id; char name[64]; } earner, manager, ceo;
This declares a struct, which has no type name, and variables earner, manager and ceo of that type. The semicolon tells the compiler when we're done with this statement. Learning when you need a semicolon after a '}' takes a little while; usually you don't, but in struct/class definition you do.
C++ added lots of things to C, but one common misunderstanding is that struct and class are somehow radically different.
C++ originally extended the struct concept by allowing you to describe functions in the context of the struct and by allowing you to describe members/functions as private, protected or public, and allowing inheritance.
When you declare a struct, it defaults to public. A class is nothing more than a struct which starts out `private.
struct
{
int id;
char name[64];
double wage;
};
class
{
public:
int id;
char name[64];
double wage;
};
The resulting definitions are both identical.
Your code does not have an access specifier, so everything in your Heap class is private. The first and most problematic issue this causes is: Nobody can call ANY of your functions, because they are private, they can only be called from other class members. That includes the constructor.
class Foo { Foo () {} };
int main()
{
Foo f;
return 0;
}
The above code will fail to compile, because main is not a member of Foo and thus cannot call anything private.
This brings us to another problem. In your code, as posted, main is a member of Foo. The entry point of a C++ program is main, not Foo::main or std::main or Foo::bar::herp::main. Just, good old int main(int argc, const char* argv[]) or int main().
In C, with structs, because C doesn't have member functions, you would never be in a case where you were using struct-members directly without prefixing that with a pointer or member reference, e.g. foo.id or ptr->wage. In C++, in a member function, member variables can be referenced just like local function variables or parameters. This can lead to some confusion:
class Foo
{
int a, b;
public:
void Set(int a, int b)
{
a = a; // Erh,
b = b; // wat???
}
};
There are many ways to work around this, but one of the most common is to prefix member variables with m_.
Your code runs afoul of this, apparently the original in C passed the array to heapify, and the array was in a local variable a. When you made a into a member, leaving the variable name exactly the same allowed you not to miss the fact that you no-longer need to pass it to the object (and indeed, your heapify member function no-longer takes an array as a pointer, leading to one of your compile errors).
The next problem we encounter, not directly part of your problem yet, is your function Heap(). Firstly, it is private - you used class and haven't said public yet. But secondly, you have missed the significance of this function.
In C++ every struct/class has an implied function of the same name as the definition. For class Heap that would be Heap(). This is the 'default constructor'. This is the function that will be executed any time someone creates an instance of Heap without any parameters.
That means it's going to be invoked when the compiler creates a short-term temporary Heap, or when you create a vector of Heap()s and allocate a new temporary.
These functions have one purpose: To prepare the storage the object occupies for usage. You should try and avoid as much other work as possible until later. Using std::cin to populate members in a constructor is one of the most awful things you can do.
We now have a basis to begin to write the outer-shell of the code in a fashion that will work.
The last change is the replacement of "HEAPSIZE" with a class enum. This is part of encapsulation. You could leave HEAPSIZE as a #define but you should expose it within your class so that external code doesn't have to rely on it but can instead say things like Heap::Size or heapInstance.size() etc.
#include <iostream>
#include <cstdint> // for size_t etc
#include <array> // C++11 encapsulation for arrays.
struct Heap // Because we want to start 'public' not 'private'.
{
enum { Size = 10 };
private:
std::array<int, Size> m_array; // meaningful names ftw.
public:
Heap() // default constructor, do as little as possible.
: m_array() // says 'call m_array()s default ctor'
{}
// Function to load values from an istream into this heap.
void read(std::istream& in)
{
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
}
return in;
}
void write(std::ostream& out)
{
for (size_t i = 0; i < Size; ++i)
{
if (i > 0)
out << ','; // separator
out << m_array[i];
}
}
int heapify(size_t index)
{
// implement your code here.
}
}; // <-- important.
int main(int argc, const char* argv[])
{
Heap myHeap; // << constructed but not populated.
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
myHead.write(std::cout);
return 0;
}
Lastly, we run into a simple, fundamental problem with your code. C++ does not have implicit multiplication. 2i is the number 2 with a suffix. It is not the same as 2 * i.
int l = 2 * i;
There is also a peculiarity with your code that suggests you are mixing between 0-based and 1-based implementation. Pick one and stick with it.
--- EDIT ---
Technically, this:
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
is poor encapsulation. I wrote it this way to draw on the original code layout, but I want to point out that one reason for separating construction and initialization is that it allows initialization to be assured that everything is ready to go.
So, it would be more correct to move the heapify calls into the load function. After all, what better time to heapify than as we add new values, keeping the list in order the entire time.
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
heapify(i);
}
Now you've simplified your classes api, and users don't have to be aware of the internal machinery.
Heap myHeap;
myHeap.load(std::cin);
myHeap.write(std::cout);

The display function does not work

I have 3 classes.
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
void afisare()
{
cout<<nr;
}
In main i have this:
piesa_c C(2, H,14,"TIPC",20);
C.afisare();
But this doesn't work.
I don't know if the "buf" was declared properly because the problem seems to be in last class.
Why?
Later Edit:
The entire code is here: http://pastebin.com/nx2FGSfe.
Now, i have this in main
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
The display function return this error
main.cpp:143:14: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
nr is not initialized in the piesa_c() constructor, meaning it will have an undefined value.
Instead of using a dynamically allocated array used a std::vector<piesa_b> instead. It will handle dynamic memory allocation and do the right thing when instances of piesa_c is copied. Using std::vector also means the nr member variable can omitted as that information can be obtained from vector::size() and the std::vector can be populated in the initializer list instead of in the constructor body:
std::vector<piesa_b> buf;
piesa_c(int n,
piesa_b *bu,
int aid,
char* tipi,
int pretzz) : piesa_a(aid,tipi,pretzz),
buf(bu, bu + nr) {}
And to invoke a member function on each element in buf:
// C++11 lambda, otherwise use
// std::vector<piesa_b>::const_iterator.
//
std::for_each(buf.begin(), buf.end(), [](piesa_b& pb) { pb.afisare(); });
If afisare() does not modify then make it const:
void afisare() const
{
}
Additonally, use std::string instead of char*. If you insist on having dynamically allocated members in the classes you need to obey the rule of three.
I am not sure what "not work" means in this context, but when you call this constructor:
piesa_c C(2, H,14,"TIPC",20);
the data member nr is not set. It can have any value that fits into an int, so when you use it to initialize an array you will get variable and weird results.
Note that you could save yourself a lot of trouble by using std::vector and std::string instead of dynamically allocated arrays and char*.

C++ Array initialization

the code below gives compilation error when I try to create test t[2];
because there is no default constructor for this.
But if I create Test t[2] = {test(1,2), test(2,3)}; Then it works fine.
1)But think of a situation, if we want to create more then 100 array element. We need to create 100 element in the curly braces like..
Test t[100] = {test(1,2), test(1,2)……/100 times/};
The above code is difficult to maintain.
One more solution is to create public member function which takes 2 integers and run in a loop. This solves the problem but i want to know any other good method.
2) If I create it using new
Test *t = new test[10];
I get compilation error(No default constructor). How to solve this.
class test
{
int _a;int _b;
public:
test(int a, int b);
void display();
};
int _tmain(int argc, _TCHAR* argv[])
{
test t[10];
for (int i = 0 ; i< 10; i++)
t[i].display();
}
In order to construct your 10 elements in the array the compiler somehow has to instaciate them through a constructor. For arrays only a default constructor (taking no arguments) can bes used, as you can not pass any arguments to the elements in the array. Therfor you have to proved a constructor
test::test()
taking no arguments.
In your example what do you expect to be displayed?
If you know that, you can write a Default CTor (one that has no parameters) and set your values to the defaults.
An example of the Default CTor:
// Variant 1: Use the initialization list
test()
: a(-1)
, b(-1)
{
}
// OR
// Variant 2: Do it in the CTor's body
test()
{
a = -1;
b = -1;
}
Note: You can write several CTors (it's called "overloading"). One that takes no parameters and sets default values and others that take parameters and set those values.
You can also define a constructor with default values for all parameters which will be used as the default constructor.
test(int a = 0, int b = 0) :_a(a), _b(b) {}
Since all parameters have default values, this constructor will be used as the default. Leaving out the initialization list or not initializing the member variables in the body of the constructor may give you random data values. Some systems may zero all memory allocations, but some do not.

Need help creating an array of objects

I am trying to create an array of class objects taking an integer argument. I cannot see what is wrong with this simple little code. Could someone help?
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
} Object;
int main (int argc, char * const argv[])
{
for(int i = 0; i < 10; i++)
{
Object o(i)[100];
}
return 0;
}
In C++ you don't need typedefs for classes and structs. So:
class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
};
Also, descriptive names are always preferrable, Object is much abused.
int main (int argc, char * const argv[])
{
int var = 1;
Object obj_array[10]; // would work if Object has a trivial ctor
return 0;
}
Otherwise, in your case:
int main (int argc, char * const argv[])
{
int var = 1;
Object init(var);
Object obj_array[10] = { var, ..., var }; // initialize manually
return 0;
}
Though, really you should look for vector
#include <vector>
int main (int argc, char * const argv[])
{
int var = 1;
vector<Object> obj_vector(10, var); // initialize 10 objects with var value
return 0;
}
dirkgently's rundown is fairly accurate representation of arrays of items in C++, but where he is initializing all the items in the array with the same value it looks like you are trying to initialize each with a distinct value.
To answer your question, creating an array of objects that take an int constructor parameter. You can't, objects are created when the array is allocated and in the absence of a trivial constructor your compiler will complain. You can however initialize an array of pointers to your object but you really get a lot more flexibility with a vector so my following examples will use std::vector.
You will need to initialize each of the object separately if you want each Object to have a distinct value, you can do this one of two ways; on the stack, or on the heap. Lets look at on-the-stack first.
Any constructor that take a single argument and is not marked as explicit can be used as an implicit constructor. This means that any place where an object of that type is expected you can instead use an instance of the single parameter type. In this example we create a vector of your Object class and add 100 Objects to it (push_back adds items to a vector), we pass an integer into push_back which implicitly creates an Object passing in the integer.
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(i);
}
}
Or to be explicit about it:
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(Object(i));
}
}
In these examples, all of the Object objects are allocated on the stack in the scope of the for loop, so a copy happens when the object is pushed into the vector. Copying a large number of objects can cause some performance issues especially if your object is expensive to copy.
One way to get around this performance issue is to allocate the objects on the heap and store pointers to the objects in your vector:
#include <vector>
int main() {
std::vector<Object*> v;
for(int i = 0; i < 100; i++) {
v.push_back(new Object(i));
}
for(int i = 0; i < 100; i++) {
delete v[i];
}
}
Since our objects were created on the heap we need to make sure that we delete them to call their deconstructor and, free their memory, this code does that in the second loop.
Manually calling delete has it's own caveats, if you pass these pointers to other code you can quickly loose track of who owns the pointers and who should delete them. An easier way to solve this problem is to use a smart pointer to track the lifetime of the pointer, see either boost::shared_ptr or tr1::shared_ptr which are reference-counted pointers :
#include <vector>
int main() {
std::vector<shared_ptr<Object> > v;
for(int i = 0; i < 100; i++) {
Object* o = new Object(i);
v.push_back(shared_ptr<Object>(o));
}
}
You'll notice that the shared_ptr constructor is explicit, this is done intentionally to make sure that the developer is intentionally stuffing their pointer into the shared pointer. When all references to an object are released the object will automatically be deleted by the shared_ptr, freeing us of the need to worry about it's lifetime.
If you want to stick to arrays, then you must either initialize manually or use the default constructor. However, you can get some control by creating a constructor with a default argument. This will be treated as a default constructor by the compiler. For example, the following code prints out the numbers 0, ..., 9 in order. (However, I'm not sure that the standard dictates that the objects in the array must be constructed in order. It might be implementation dependent, in which case the numbers may appear in arbitrary order.)
#include <iostream>
using namespace std;
struct A {
int _val;
A(int val = initializer()) : _val(val) {}
static int initializer() { static int v = 0; return v++; }
};
int main()
{
A a[10];
for(int i = 0; i < 10; i++)
cout << a[i]._val << endl;
}

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.