Hello everybody
I am doing a little code to learn a bit more about C++. Do not be amazed if you find that code useless, it is mainly just for me to improve. :) This is my first C++ program and I started few days ago... [/I]One class is used for "random number generation" purposes, and "Printer" would be used to print some infos. The output is 50 random numbers displayed one per line:
General information:
The value of system time (unsigned) is: 1235691452
Test of randomGenerator:
0 1
1 34
2 1
3 46
4 22
5 43
6 40
7 15
8 32
9 10
10 23
etc...
I have few problems:
One concerns is about my use of the Printable "interface". I am not familiar with this in C++.
Another one is I guess in my architecture; uncertainties about where to define variable_toString() method. Uncertainties about loads of things actually! :confused:
All of these unable me to print a RandomGenerator instance along with its internals.
Here is the code:
- Printable.h
I use this one to define any class as "printable"; having a toString method.
#ifndef PRINTABLE_H
#define PRINTABLE_H
#include "Printer.h"
class Printable {
protected:
virtual const std::string toString() = 0;
};
#endif
- RandomGenerator.h
#ifndef RANDOM_GENERATOR_H
#define RANDOM_GENERATOR_H
#include "Printable.h"
/*
* This class defines a random generator used for different purposes in this program.
*/
class RandomGenerator : public Printable {
private:
unsigned int lowest_number;
unsigned int highest_number;
unsigned int range;
unsigned long seed;
public:
RandomGenerator(unsigned int _lowest_number, unsigned int _highest_number);
unsigned long generate_seed(unsigned int _coeff);
unsigned int generate_rand();
virtual const std::string toString();
}; // End of class
#endif
- RandomGenerator.cpp
including RandomGenerator.h uniquely.
I skip the useless stuffs and give only toString() method implementation.
// Typecast "this" to string
const std::string RandomGenerator::toString() {
Printer *rg_printer = NULL;
rg_printer = new Printer();
std::stringstream sstream (stringstream::out);
std::string object_to_string;
sstream << "Random minima: " << rg_printer->variable_toString(lowest_number)
<< " Random maxima: " << rg_printer->variable_toString<unsigned int>(highest_number)
<< " Current seed: " << rg_printer->variable_toString<unsigned long>(seed);
object_to_string = sstream.str();
return object_to_string;
}
Yeah I know, this instanciation + use of Printer here looks definitely dodgy. I started by putting this function directly in RandomGeneration class, doing the same thing... and it was working! (Yeah!! that's enough for me to be happy! :cool: ) But obviously, if you have to redefine it everytime... That's why it is now in Printer class. But... not working!
I got this kind of Linker errors:
[Linker error] undefined reference to `std::string Printer::variable_toString<unsigned long>(unsigned long)'
[Linker error] undefined reference to `std::string Printer::variable_toString<unsigned int>(unsigned int)'
[Linker error] undefined reference to `std::string Printer::variable_toString<unsigned int>(unsigned int)'
Related to the three numbers I am putting into the stringstream, or I should rather say, to the three calls of variable_toString() method:
- Printer.h
#ifndef PRINTER_H
#define PRINTER_H
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// Would be used to print/retrieve info
class Printer {
private:
public:
Printer();
void print_blank_line();
void print_string(std::string _string_to_print);
template<typename Variable>
std::string variable_toString(Variable _variable);
};
#endif
- Printer.cpp
including Printer.h only.
I skip the useless stuffs and give only variable_toString() method implementation.
// Typecast a variable to string
template<typename Variable>
string Printer::variable_toString(Variable _variable) {
stringstream sstream (stringstream::out);
string variable_to_string;
sstream << _variable;
variable_to_string = sstream.str();
return variable_to_string;
}
And finally the main (sorry for this big amount of code):
//#include "stdafx.h"
#include "RandomGenerator.h"
#include "Printer.h"
using namespace std;
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int main (int argc, char *argv[]) {
RandomGenerator *random_1_50 = NULL;
Printer *m_printer = NULL;
int chromosome[50];
int i;
m_printer = new Printer();
random_1_50 = new RandomGenerator(1, 50);
for (i = 0; i < ARRAYSIZE(chromosome); i++)
chromosome[i] = 0;
m_printer->print_string("General information: ");
// Output system time used to seed random generator
cout << "The value of system time (unsigned) is: " << (unsigned) time(0) << endl;
m_printer->print_blank_line();
m_printer->print_string("Test of randomGenerator: ");
m_printer->print_string(random_1_50->toString());
srand(random_1_50->generate_seed(1));
for (i = 0; i < ARRAYSIZE(chromosome); i++) {
chromosome[i] = random_1_50->generate_rand();
cout << i << " " << chromosome[i] << endl;
}
m_printer->print_blank_line();
system("PAUSE");
return EXIT_SUCCESS;
} // End of main
This is obviously a bad design or rather weird anyway.
Why do I get these errors?
What about my use of the interface?
What about my use of the template? Why do I have to define it both in Printer .h and .cpp?
What about the way I include file? I tried to include a minimum; so that I can learn about "who is coming from where?". In Printable I call a bunch of headers which are used only in Printer. The idea was to be able to create any printable class by just implementing Printable and including Printer.h. Is it a bad choice? What is the real way to do it?
Other point: I saw there are easier way to do what I want, overloading a function based on iostreams, stuffs like that. But I would like to get this "way" working first if possible. I do not like being in these situations of uncertainties. I am to the point where I stare at my computer for hours, seeing nothing wrong but still having this "it_must_be_coming_from_me"-ish attitude! :confused:
But still, could be a story of compiler no? I use Dev-C++ with apparently g++ compiler.(That is what is written in the compiler log).
I think I am going to stop here for now. I can hear everybody saying: "Finally!!", and I apologize for any inconvenience this post could have caused to any of you! :D
Still any advices, hints, links, examples - even greetings - are welcomed!
cheers