
// This example illustrates declarations, definitions, default constructors, copy constructors, and assignments.

#include <iostream>
#include <cstdlib>
#include <vector>

void line_of_code(int linenum) { std::cout << "line: " << linenum << std::endl; return; }

// Declaration: func is a function that takes a double argument and returns an int.
// No code is generated yet, but the compiler will know what the type of func is.
// The actual implementation can be defined in another compilation unit.
int func(double);

// Definition: this tells the compiler what func should actually do.
// There will be code generated for this definition.
int func(double rhs)
{
	int x = rhs;
	rhs -= x;
	rhs *= 10;
	// by the way, func returns the first digit after the decimal point, with sign
	return rhs; 
}

///////////////////////////////////////////////////////////////////////////////

// Declaration: Something is a class.  Nothing known about it thus far!
class Something;

// We can already define a pointer to Something and assign an initial value to it.
Something * sth_ptr = 0;

// Definition of class Something
class Something
{
	public:
		int a;
		double b;

		// Declaration of member function
		void dump( std::ostream& os );

		// Default constructor
		Something()
			: a(0), b(0)
		{
			std::cout << "default constructor called" << std::endl;
		}

		// Copy constructor
		Something(const Something& rhs)
			: a(rhs.a),
		 		b(rhs.b) 
		{
			std::cout << "copy constructor called" << std::endl;
		}

		Something & operator=(const Something& rhs)
		{
			a = rhs.a;
			b = rhs.b;
			std::cout << "assignment operator called" << std::endl;
		}

};

// Definition of member function
void Something::dump( std::ostream& os )
{
	os << "[ this=" << this << ", a=" << a << ", b=" << b << " ]" << std::endl;
}

int main( int argc, char ** argv )
{
	if ( argc != 2 ) { std::cerr << "???" << std::endl; return 0; }
	double number = atof(argv[1]);
	std::cout << "input:  " << number << "\noutput: " << func(number) << std::endl;

	line_of_code(__LINE__);
	
	// define an instance sth of the class Something
	Something sth;

	// assign values to members of sth
	sth.a = 8;
	sth.b = 0.125;
	
	// Call a member function of sth
	sth.dump(std::cout);
	// sth_ptr->dump(std::cout); // BANG!!! sth_ptr is zero, see above.

	// Assign the address of sth to the pointer sth_ptr
	sth_ptr = &sth;

	// Assign a value to member a of sth (through sth_ptr)
	sth_ptr->a = 16;
	sth_ptr->b = 0.25;

	// Call a member function of sth
	sth.dump(std::cout);
	// Call a member function of sth through a pointer.
	// Note this is actually the same instance, as we can read off from the "this" pointer
	sth_ptr->dump(std::cout);

	line_of_code(__LINE__);
	
	Something sth_2(sth);
	
	line_of_code(__LINE__);
	
	Something sth_3;
	
	line_of_code(__LINE__); // 114
	
	sth_3 = sth;

	line_of_code(__LINE__);
	
	std::vector<Something> sth_vec(4);

	line_of_code(__LINE__);
	
	std::vector<Something> sth_vec2(4,sth);

	return 0;
}




