[Home] [Downloads] [Search] [Help/forum]

Gammon Software Solutions forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  Programming
. -> [Folder]  General
. . -> [Subject]  Forcing the Explicit Constructor

Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?
(New message)
Subject: Forcing the Explicit Constructor
Name:
Your forum user name.
Register forum user name
Password:
Your forum password.
Forgotten password?
Message:
Message to be posted (in English, please).
Forum codes:
Check this if your message uses 'forum codes' or templates (auto-detected for new posts).
Forum codes Templates

Save this message ...


Subject review (reverse sequence)

Pages: 1  2 

Posted by Terry   USA  (87 posts)  [Biography] bio
Date Fri 20 Nov 2009 06:15 PM (UTC)  quote  ]
Message
Vectors are what I ended up using in the end, and I also ended up taking out and moving around and doing a whole bunch of stuff with a whole bunch of stuff to basically make it so my program completely changed. :P If anyone's interested, I can post my work so you guys can see my end result, but it's not too terribly exciting imo. :D
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio   Moderator
Date Wed 18 Nov 2009 07:41 PM (UTC)  quote  ]
Message
Terry said:
Oh, and about the function creation thingy, it's because you CAN'T call an empty constructor.

What do you mean? If you have a class A with a constructor that takes no parameters (or all parameters have default values) then you can do things like:

A a = A();

which is calling the "empty" constructor. (Assuming that's what you mean by "empty" here.)

Terry said:
It defaults to the first one (probably for the backward compatibility stuff, although it is probably also because functions are much more common than constructors).

It's the only way to write a forward declaration of a function that takes no parameters, so there isn't really any other option.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Twisol   USA  (2,229 posts)  [Biography] bio
Date Wed 18 Nov 2009 01:12 AM (UTC)  quote  ]
Message
More simply, you can create arbitrary-size arrays at runtime just with dynamic allocation, i.e.


int[] int_arr = new int[ARR_SIZE];


The memory referred to by int_arr is stored on the heap, not the stack, so you can store the pointer and use it elsewhere. However you do need to be sure to call delete[] on it when you're done with it, i.e.

delete[] int_arr


I prefer vectors, as Nick showed, when I don't have a hard limit to the amount of data I'm storing, or when there's no reason to limit it in the first place. But if I was just going to store the results of exactly 64 dice rolls, I'd probably use an array.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Wed 18 Nov 2009 12:59 AM (UTC)  quote  ]
Message
No worries.

By the way, you *can* dynamically create arrays using the Standard Template Library (STL). I have a heap of posts about it on this forum.

Something like:


vector<int> dice;


Then you can put as many items as you like into it with push_back. You don't need to impose any arbitrary limits.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Terry   USA  (87 posts)  [Biography] bio
Date Tue 17 Nov 2009 10:20 PM (UTC)  quote  ]
Message
Nick Gammon said:

You are storing shorts (16 bits) but getting an int (32 bit) as the argument. You are just asking for compiler warnings here.


I don't know why I'm doing it either. :D Fixed... I guess this is what happens when you do an assignment the day before its due, when you're half asleep. >_> You run into bugs everywhere, you make sloppy mistakes, and you stumble upon rather crazy solutions to problems that don't even exist. XD (Oh, and then you start pulling out your hair and scratching off your eyes when the compiler doesn't obey. :P)

In any case, I realized that, because I put default arguments in my constructor, it became the default constructor. The reason is, if you tried to overload the constructor with the default, you'd get yelled at for an ambiguous overload. So Dice d1; would indeed work. >:C I'm really sorry for wasting everyone's time. D:

Oh, and about the function creation thingy, it's because you CAN'T call an empty constructor. The way the C++ naming process works is that it can read A foo() as function foo which returns an object of class A, or it might be a constructor. It defaults to the first one (probably for the backward compatibility stuff, although it is probably also because functions are much more common than constructors).

About the *_dice, I guess I'll just have to make a vector. I was attempting to dynamically create an integer array via pointers, but the data gets cleaned, so the pointer becomes null. =\ Oh well. :)

Anyway, thanks for the help. :D And I'm sorry again for wasting time, but I appreciate all your work. :D
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 10:18 PM (UTC)  quote  ]
Message
Hmmm - I don't really want to post a completely revised version as I suspect this is some sort of homework or something, and even if not, you wouldn't learn anything if someone else does all the work.

Basically you need to carefully revise everything you have done.


  • For example, this doesn't make any sense:

    
    Dice::Dice( const unsigned int numDice = 2, const unsigned int sides = 6 )
    :NUM_DICE((numDice <= MAX_DICE) ? numDice : MAX_DICE), DICE_SIZE((sides <= MAX_SIZE) ? sides : MAX_SIZE)
    


    You have declared NUM_DICE and DICE_SIZE as:

    
    extern const unsigned short NUM_DICE, DICE_SIZE;
    


    Since these are member variables for this particular instance of the object that should not be extern.

  • Then I would make up your mind what your data type is going to be. So far you have used unsigned int, int, unsigned short and long. Choose a type and stick to it (eg. short).

  • You have declared a pointer:

    
    unsigned int *_dice;
    


    This means you need to allocate memory for it (eg. with new or malloc). This line won't do it:

    
    _dice = dice
    


    That is just assigning a local variable in rollDice to the pointer. Even if the compiler accepts this, it will crash because the memory will go out of scope as soon as the function returns.

  • This line is inconsistent:

    
    Dice(const int unsigned numDice, const unsigned int sides);
    


    One is "int unsigned" and the other is "unsigned int". Even if they are semantically the same (David would know), be consistent.

  • You have in your class declaration:

    
    int getDie(const unsigned int die) const;
    


    But the implementation is:

    
    int Dice::getDie( const unsigned short die ) const
    


    Again, a confusion between int and short. This will make the compiler complain.

  • You create a dice like this:

    
    Dice d1(1, 5);
      std::cout << "d1: " << printSum(d1) << std::endl;
    


    This is passing down a copy of d1 by value, but the function printSum expects a pointer:

    
    std::string printSum(Dice *roll)
    


  • I am a little surprised the compiler let you get away with this (maybe it didn't):

    
    int dice[NUM_DICE];
    


    You can't dimension an array with a variable. This is what dynamic memory allocation is all about.



I suggest starting again. Check your understanding of pointers and arrays. Be consistent in data types. If a function is declared to take a pointer, make sure you pass a pointer to it. I would steer clear of the stuff about "extern" for the maxima. A simple declaration like this would suffice for now:


#define MAX_DICE 100
#define MAX_SIZE 1000


Make the raw methods and check the compiler accepts the declarations before putting code in them.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 09:51 PM (UTC)  quote  ]
Message
Why do this?


Dice(const int unsigned numDice, const unsigned int sides);

...

private:
	static const unsigned short MAX_DICE, MAX_SIZE;
	extern const unsigned short NUM_DICE, DICE_SIZE;


You are storing shorts (16 bits) but getting an int (32 bit) as the argument. You are just asking for compiler warnings here.

Anyway, let me see if I can make this work a bit better ...

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Terry   USA  (87 posts)  [Biography] bio
Date Tue 17 Nov 2009 09:00 PM (UTC)  quote  ]
Message
Nick Gammon said:

I withdraw my comment about needing to define it first, but this looks strange:


extern const unsigned short NUM_DICE, DICE_SIZE;


What are you trying to do exactly?

I want the number and size of dice to be set by the constructor, which is why I wanted to require the constructor in the first place. :B I made a default parameter for both, thinking that it would make Dice d1(2, 6); behave like Dice d1();, but apparently that isn't the case. =\
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio   Moderator
Date Tue 17 Nov 2009 08:52 PM (UTC)  quote  ]
Message
Also, this is wrong:
const roll = 1 + (std::rand() % DICE_SIZE);

you need a type here, like 'int' or something.
Your probability math is not strictly correct either, but it's close enough for government work I suppose.

(You're assuming that each number has an equal number of occurrences in the range 0 .. std::rand(). But if std::rand() -- which stops at RAND_MAX, IIRC -- doesn't land evenly on a multiple of DICE_SIZE, some numbers will be slightly less probable. But if RAND_MAX is sufficiently large, you won't really notice this.)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 08:47 PM (UTC)  quote  ]
Message
I withdraw my comment about needing to define it first, but this looks strange:


extern const unsigned short NUM_DICE, DICE_SIZE;


What are you trying to do exactly?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 08:44 PM (UTC)  quote  ]
Message

#include "dice.h"


const unsigned short Dice::MAX_DICE = 100;
const unsigned short Dice::MAX_SIZE = 1000;



Inside dice.h it needs to know MAX_DICE, but you define it too late. You need to rework this.

Terry said:

Oh geez. Wow. I didn't realize I deleted the question. :| I thought that I'd accidentally reposted the question, because it was at the bottom... I'm not quite sure how that happened.


When you reply, it puts the posts in reverse order, so the one you are replying to is near the top.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Terry   USA  (87 posts)  [Biography] bio
Date Tue 17 Nov 2009 08:43 PM (UTC)  quote  ]
Message
Oh geez. Wow. I didn't realize I deleted the question. :| I thought that I'd accidentally reposted the question, because it was at the bottom... I'm not quite sure how that happened... =\ Apologies.
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 08:40 PM (UTC)  quote  ]

Amended on Tue 17 Nov 2009 08:41 PM (UTC) by Nick Gammon

Message
There is no [code=<something>] tag, just use [code]

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Terry   USA  (87 posts)  [Biography] bio
Date Tue 17 Nov 2009 08:39 PM (UTC)  quote  ]

Amended on Tue 17 Nov 2009 08:53 PM (UTC) by Terry

Message
Yeah, this whole time I've been testing out stuff that you guys've been talking about, which is why I haven't responded. I'm getting a lot of errors, from this code, and I can't really understand why. :P

// dice.h
#include <cstdlib>


class Dice
{
public:
	Dice(const int unsigned numDice, const unsigned int sides);
	void rollDice();
	int getDie(const unsigned int die) const;
	int getDice() const;
	int getSum() const;
	int getPoint() const;
private:
	static const unsigned short MAX_DICE, MAX_SIZE;
	extern const unsigned short NUM_DICE, DICE_SIZE;
	unsigned int *_dice;
	unsigned long _sumOfDice;
};

// dice.cpp
#include "dice.h"


const unsigned short Dice::MAX_DICE = 100;
const unsigned short Dice::MAX_SIZE = 1000;


Dice::Dice( const unsigned int numDice = 2, const unsigned int sides = 6 )
:NUM_DICE((numDice <= MAX_DICE) ? numDice : MAX_DICE), DICE_SIZE((sides <= MAX_SIZE) ? sides : MAX_SIZE)
{
}


void Dice::rollDice()
{
	int dice[NUM_DICE], sum;
	for( unsigned short die = 0; die < NUM_DICE; ++die )
	{
		const roll = 1 + (std::rand() % DICE_SIZE);
		dice[die] = roll;
		sum += roll;
	}
	
	_dice = dice, _sumOfDice = sum;
}


int Dice::getDice() const
{
	return NUM_DICE;
}

int Dice::getDie( const unsigned short die ) const
{
	if( die >= NUM_DICE )
		return -1;

	return _dice[die];
}

int Dice::getSum() const
{
	return _sumOfDice;
}


// main.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>

#include "dice.h"


std::string printSum(Dice *roll);


int main()
{
  std::srand(static_cast<unsigned int>(std::time(0)));

  Dice d1(1, 5);
  std::cout << "d1: " << printSum(d1) << std::endl;
  Dice d2();
  std::cout << "d2: " << printSum(d2) << std::endl;

  return EXIT_SUCCESS;
}

std::string printSum(Dice *roll)
{
  std::ostringstream oss;

  for( unsigned short i = 0; i < roll.getDice() - 1; ++i )
    oss << roll.getDie(i) << " + ";
  oss << roll.getDie(roll.getDice() - 1) << " = " << roll.getSum();

  return oss.str();
}


[brainfrz@li100-29 dice]$ g++ -o main dice.cpp main.cpp
dice.h:15: error: storage class specified for âNUM_DICEâ
dice.h:15: error: storage class specified for âDICE_SIZEâ
dice.cpp: In member function âvoid Dice::rollDice()â:
dice.cpp:19: error: ISO C++ forbids declaration of ârollâ with no type
dice.cpp:24: error: invalid conversion from âint*â to âunsigned int*â
dice.cpp: At global scope:
dice.cpp:33: error: prototype for âint Dice::getDie(short unsigned int) constâ does not match any in class âDiceâ
dice.h:9: error: candidate is: int Dice::getDie(unsigned int) const
dice.h:15: error: storage class specified for âNUM_DICEâ
dice.h:15: error: storage class specified for âDICE_SIZEâ
main.cpp: In function âint main()â:
main.cpp:17: error: cannot convert âDiceâ to âDice*â for argument â1â to âstd::string printSum(Dice*)â
main.cpp:19: error: cannot convert âDice (*)()â to âDice*â for argument â1â to âstd::string printSum(Dice*)â
main.cpp: In function âstd::string printSum(Dice*)â:
main.cpp:28: error: request for member âgetDiceâ in ârollâ, which is of non-class type âDice*â
main.cpp:29: error: request for member âgetDieâ in ârollâ, which is of non-class type âDice*â
main.cpp:30: error: request for member âgetDieâ in ârollâ, which is of non-class type âDice*â
main.cpp:30: error: request for member âgetDiceâ in ârollâ, which is of non-class type âDice*â
main.cpp:30: error: request for member âgetSumâ in ârollâ, which is of non-class type âDice*â
[Go to top] top

Posted by Nick Gammon   Australia  (18,772 posts)  [Biography] bio   Forum Administrator
Date Tue 17 Nov 2009 08:39 PM (UTC)  quote  ]
Message
For the record, the original question was:

Quote:

I was wondering if it was possible to "force" an object to be constructed via the explicit constructor, rather than the default one? What I want is for something like
Class myClass; to be handled the same as Class myClass();. Either that, or make it so that member functions can see if the explicit constructor was called?

At first, I thought of doing something like bool _isConstructed; and put _isConstructed(true), in the initializer list, but then I realized there's no way of knowing it will be false originally... Is there no way of doing something like any of the ideas I've mentioned?


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


4,661 views.

This is page 2, subject is 2 pages long:  [Previous page]  1  2 

[Reply to this subject]  Reply to this subject   [New subject]  Start a new subject   [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

[Home]

Written by Nick Gammon - 5K

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( http://www.gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Internet Contents Rating Association (ICRA) - 2K]    [Web site powered by FutureQuest.Net]