|
||
|
|
#1 (permalink) |
|
Forum Expert
|
Okay, so I know that in C#, I can create a class with a custom constructor, and then make an array of that class and call the constructors in the initialization. This may sound confusing, so I'll give an example.
Code:
public class Class1
{
public string string1;
public Class1(string s)
{
string1 = s;
}
}
public class Class2
{
public Class2()
{
Class1[] classes = new Class1[]
{
new Class1("Hello"), //Calling custom constructors in initialization of array
new Class1("Goodbye")
};
}
}
Code:
class Class1
{
public:
string string1;
Class1(string s)
{
string1 = s;
}
}
class Class2
{
public:
Class1 *classes;
Class2()
{
classes = new Class1[] //Syntax error
{
Class1("Hello"),
Class2("Goodbye")
};
}
~Class2()
{
delete [] classes;
}
}
That C++ code gives me syntax errors in the initialization of "classes". What would be the best way to do what I am trying to do? I can't really seem to find a solution, so any help is appreciated. Thanks |
|
|
|
|
|
#2 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
try:
Class1 * classes=new Class1[2]; classes[0]=new Class1("asds"); classes[1]=new Class1("sads");
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." Last edited by noobie; 11-09-2006 at 10:48 AM. |
|
|
|
|
|
#6 (permalink) | |
|
Forum Expert
|
Quote:
Code:
Class1 *classes = (Class1 *) calloc( 2, sizeof(Class1) );
classes[0] = Class1("hey");
classes[1] = Class1("heeey");
__________________
|
|
|
|
|
|
|
#7 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
yes, it is called dynamic allocation and if you use arul's (first) example, memory is allocated in compile time.
if you use C++, get used to pointers.. ![]()
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#8 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
arul : if you are gonna do it in C-style, it is better to use malloc rather than calloc..
anyway, C is annoying, go with C++ ![]()
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#9 (permalink) | |
|
Forum Expert
|
an array and a pointer variable are basically synonymous terms.
by Code:
Class1 classes[] = { Class1("Hello"), Class1("Goodbye") };
Quote:
Last edited by Nochte; 11-09-2006 at 01:36 PM. |
|
|
|
|
|
|
#10 (permalink) |
|
Forum Expert
|
Technically, about the best way to do what you want to do is using malloc() with placement-new.
Code:
Class1 *classes = static_cast<Class1 *>(malloc(sizeof(Class1) * 2));
new(&classes[0]) Class1("Hello");
new(&classes[1]) Class1("Goodbye");
This is, technically, the best way to do it as it avoids any unnecessary temporaries or initialization that the other examples had (of course, this is assuming the optimizer doesn't just get rid of them completely, which it may very well do). Of course, all of the other ways are easier to understand, thus they have their own merits (Except for noobie's of course, which leaks memory, if it were even valid to assign a Class1 * to a Class1 at all ).However, as it is, none of the examples, which have been using milt's original Class1 definition, have been correct, other than mine and arul's. This is because when milt defined a constructor for Class1 that took a std::string parameter, he hid the default constructor for Class1, thus using new to create multiple Class1 objects is illegal as it requires Class1 to have a default constructor to call on each of the objects. Using malloc() (or calloc() for that matter) elides this restriction, as it doesn't call any constructors, it only allocates memory (including calloc(), though it does zero memory out for you). Also, in arul's method, classes is a pointer variable, it just doesn't look like it. In C/C++, all arrays decay to pointer's, thus classes is usable in (almost) any place where a pointer would be allowed. edit: Darn, Nochte beat me to my last statement. Last edited by Sep102; 11-09-2006 at 02:03 PM. |
|
|
|
|
|
#11 (permalink) |
|
Forum Expert
|
Code:
class Calendar
{
public:
int year;
int month;
Month *months;
Calendar()
{
Month table[] =
{
Month("January", 31),
Month("February", 28),
Month("March", 31),
Month("April", 30),
Month("May", 31),
Month("June", 30),
Month("July", 31),
Month("August", 31),
Month("September", 30),
Month("October", 31),
Month("November", 30),
Month("December", 31)
};
months = &table; //Line of error
}
~Calendar()
{
delete [] months;
}
}
I wanted to try it this way, but for some reason I keep getting that error. Shouldn't it technically work? |
|
|
|
|
|
#12 (permalink) |
|
Forum Newbie
Join Date: Nov 2002
Posts: 89
|
If I understand you correctly, you want to initliaze a class with a string?
Code:
#include <string>
class Class1
{
public:
Class1(const std::string &="")
public:
std::string s;
};
Code:
Class1::Class1(const std::string &var)
{
s= var;
}
|
|
|
|
|
|
#13 (permalink) |
|
Forum Expert
|
If this were C, then yes, but C++ has stricter typing than C does, so no. What you're doing in this case is tring to assign a Month ** to a Month *. table in this case is a Month[12] or array of 12 Month objects, taking the address of that with (&) returns a pointer to a pointer to a Month, which, like I said, can't be assigned to a Month *.
Try: Code:
months = &table[0]; However, this code won't work as you think. You're trying to keep table around in memory for the life of the Calendar instance, however, using Month table[] = {...} is not the same thing as using Month *table = new Month[12] even though they're both pointers. table, as it is, sits on the stack for the duration of the constructor, then is automatically cleaned up, like any local variable is. Objects created using new or memory allocated using malloc() needs to be free'd or delete'd by you, which is why they stick around for as long as you want them to. What you need to do is create table using new or malloc(), then initialize each element in it, then assign it to months, as then it will live on the heap, you can delete[] (or free()) it fine, and everything will be right in the world. Last edited by Sep102; 11-09-2006 at 02:04 PM. |
|
|
|
|
|
#14 (permalink) |
|
Forum Expert
|
Okay, so basically I'm stuck with this?
Code:
class Calendar
{
public:
int year;
int month;
Month *months;
Calendar()
{
months = new Month[12];
months[0] = Month("January", 31);
months[1] = Month("February", 28);
months[2] = Month("March", 31);
months[3] = Month("April", 30);
months[4] = Month("May", 31);
months[5] = Month("June", 30);
months[6] = Month("July", 31);
months[7] = Month("August", 31);
months[8] = Month("September", 30);
months[9] = Month("October", 31);
months[10] = Month("November", 30);
months[11] = Month("December", 31);
}
~Calendar()
{
delete [] months;
}
}
|
|
|
|
|
|
#15 (permalink) |
|
Forum Expert
|
Pretty much, I can give you a "possibly" more appealing way that uses std::copy from the algorithm header, but that's about it.
Code:
#include <algorithm>
/*...*/
Calendar()
{
Month table[] =
{
Month("January", 31),
Month("February", 28),
Month("March", 31),
Month("April", 30),
Month("May", 31),
Month("June", 30),
Month("July", 31),
Month("August", 31),
Month("September", 30),
Month("October", 31),
Month("November", 30),
Month("December", 31)
};
months = new Month[12];
std::copy(&table[0], &table[12], months);
}
Last edited by Sep102; 11-09-2006 at 02:18 PM. |
|
|
|
|
|
#17 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
thats not a good example, you are wasting memory..
I would use something like this: Code:
class Calendar{
public:
Month * table;
Calendar()
{
table =new Month[12]; //have a default const for Month
//initialize your private values
table[0]=Month("January", 31);
table[1]=Month("February", 28);
table[2]=Month("March", 31);
table[3]=Month("April", 30);
table[4]=Month("May", 31);
table[5]=Month("June", 30);
table[6]=Month("July", 31);
table[7]=Month("August", 31);
table[8]=Month("September", 30);
table[9]=Month("October", 31);
table[10]=Month("November", 30);
table[11]=Month("December", 31);
}
~Calendar()
{
delete [] table;
}
};
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." Last edited by noobie; 11-09-2006 at 02:55 PM. |
|
|
|
|
|
#18 (permalink) |
|
Forum Expert
|
Yes, it is wasting memory, for the duration of the constructor, then table is automatically cleaned up along with each of its entries while months sticks around with each of the entries on the heap, essentially trading "space" (constructing each month on the stack, which isn't very much of it in this case) and some time (default allocating months and copying table to months, still minuscule) for convenience.
I was trying to give an example that would use as much of milt's code as possible, had I wanted to give an optimized example, I would have, such as: Code:
Month * table;
Calendar()
{
// No need for default constructor and no extra work default
// Constructing what we're about to reconstruct, yay!
table = static_cast<Month *>(malloc(sizeof(Month) * 12));
//initialize your private values, no temporaries here
new(&table[0]) Month("January", 31);
new(&table[1]) Month("February", 28);
new(&table[2]) Month("March", 31);
new(&table[3]) Month("April", 30);
new(&table[4]) Month("May", 31);
new(&table[5]) Month("June", 30);
new(&table[6]) Month("July", 31);
new(&table[7]) Month("August", 31);
new(&table[8]) Month("September", 30);
new(&table[9]) Month("October", 31);
new(&table[10]) Month("November", 30);
new(&table[11]) Month("December", 31);
}
~Calendar()
{
for(Month *first = &table[0]; first != &table[12]; ++first)
{
first->~Month();
}
free(table);
}
I like the other example I gave more though, since it uses milt's code to construct the table on the stack and also looks quite a bit cleaner and easier to follow (especially from a more C# standpoint) than this or your example. Plus, you could just as easily have made table in some static const object that would contain all of the months for the life of the program that got copied to a member in Calendar each time a Calendar is constructed (if you want a mutable calendar, otherwise it could just hold a pointer to the table). All with minimal effort from what milt had above. Last edited by Sep102; 11-09-2006 at 03:40 PM. |
|
|
|
|
|
#19 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
well, I think that wasnt hard to understand and it is the most known syntax for memory allocation in C++, so he should get used to that one.
i have never used your syntax thb. and i tried that one just out of curiosity and it gives me a memory error "just after program exit" if you use strings instead of char*. so he needs to use C-style strings and all that stuff which is really not easy for a beginner.
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." Last edited by noobie; 11-09-2006 at 04:10 PM. |
|
|
|
|
|
#20 (permalink) |
|
Forum Expert
|
Yeah, I was trying to stay basic here, as I have just started a college C++ course. I know the basic concepts of pointers and stuff, but not all of their functionality.
One of my first assignments is to make a console app that asks for a year and month, and will spit out a calendar for that month. You have to take leap years into account, etc... but that is the easy part TBH |
|
|
|
|
|
#21 (permalink) |
|
Forum Expert
|
You've never used the syntax because placement-new isn't really used all too often, at least as far as I've seen. It can be really useful when you actually need it, but in general standard new provides most of the functionality you would need (Or, at least, that's my take on the matter).
And, technically my (milt's) example uses the same method for memory allocation, I just construct the instances of the Month in a different way, closer to the way C# does it then copied them over to where I was going to persist them. Really, you wouldn't do it your way either, in general, maybe (Probably not still though, if I was expecting to construct multiple objects at once as an array on the heap, I'd provide some Initialize() function or something of the sort rather than calling the constructor on each of them after allocating them), but at least in this instance it's not really a good idea to re-create the months every time, at least as it is. Like I said earlier, it would be a better idea to create them once then make a copy of them each time they're needed for a new instance (if it's mutable, of course), of which my example is very well suited to perform. Last edited by Sep102; 11-09-2006 at 06:40 PM. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|