Hello. I am trying to figure out how to pass parameters to a constructor using new. Right now I am allocating for an object and then assigning values to the string parameters. I'd like to pass the values and have them created in the second constructor.
So the object created with new is of card_class
1 2 3 4 5 6 7 8 9 10
class card_class {
public:
string answer;
string question;
int score;
card_class(void);
card_class(const string quest, const string ans);
};
I'd like to alter this so that the line card = new(card_class) can pass the parameters to assign to the values in card_class instead of having to assign them later in the function. How can I do this?
// Includes you'll need
#include <algorithm>
class deck_class: ...
{
...
public:
...
// A little functor to take two strings at a time and add them to a deck
struct take_two
{
card_class& cards;
string question;
take_two( card_class& cards ): cards( cards ) { }
voidoperator () ( const string& s )
{
if (question.empty()) question = s;
else
{
cards.push_back( new card_class( question, s ) );
question.clear();
}
}
};
};
constchar* const card_pile[] = {
"How does it work?",
"Like a charm.",
"How do you mean?",
"It's magic."
};
// Fill my deck_class, 'deck', with the questions and answers interleaved in the static 'card_pile'.
for_each(
card_pile,
card_pile +(sizeof( card_pile ) /sizeof( card_pile[ 0 ] )),
deck_class::take_two( deck.cards )
);
Aye, right now I am reading from a static array hard coded into the program, but I am in the process of changing this to be able to read from files so that the program can be used with different lists.
Thanks for the suggestion about the 2 strings at a time functor. I'm not quite following how the take_two is working though, specifically:
take_two( card_class &cards): cards( cards ) {}
// Here's a little helper class to overload >> to read an entire line at a time
// (that is, without clobbering the normal string >> function).
class line_t: public std::string { };
istream& operator >> ( istream&ins, line_t& line )
{
string result;
getline( ins, result );
return result;
}
// For every two lines in the file, add a card as (question, answer)
for_each(
istream_iterator <line_t> ( cin ),
istream_iterator <line_t> (),
deck_class::take_two( deck.cards )
);
The way that take_two works is a pretty simple trick. You will see it right away.
Every time the for_each() feeds it a new string (via the () operator function), it checks to see if it already has the last string given to it. If not, it just remembers the string and returns. But if it already remembered a string, now it has two strings that it can use to make a new Q&A card.
Adding a new card is a little tricky though: there is the need to allocate one on the heap and then stick the address in the deck of cards (a list of pointers to a card). So to keep it simple the take_two object also keeps a reference to the card_class container that it can use to add the card.