#include <iostream>
#include <string>
using namespace std;
class Class
{
public:
Class(); // default constructor
Class(string); // name parameterized constructor
Class(string, int); // name and data parameterized constructor
Class(const Class&); // copy constructor
~Class(); // destructor
Class& operator=(const Class&); // assignment operator
void setData(int s);
int getData() const;
string getName() const;
// the ultimate const correctness nightmare
const Class* const pass_by_reference_using_const_reference_return_pointer(const Class& o) const;
private:
string name;
int data;
};
Class::Class()
{
name = "default_constructed";
data = 0;
cout << "default constructor name: " << name << " data: " << data << endl;
}
Class::Class(const Class& other)
{
name = "copy_constructed";
data = other.data;
cout << "call to copy constructor" << endl;
cout << "data copied but name will stay \"copy_constructed\"" << endl;
cout << "at end of copy constructor name: " << name << " data: " << data << " copied from name: " << other.getName() << " data: " << other.getData() << endl;
}
Class::~Class()
{
cout << "destructor name: " << name << " data: " << data << endl;
}
Class& Class::operator=(const Class& rValue)
{
cout << "call to operator=" << endl;
cout << "this is object name: " << name << " data: " << data << endl;
data = rValue.data;
cout << "data copied but name will stay the same" << endl;
cout << "at end of operator= name: " << name << " data: " << data << " assigned from name: " << rValue.getName() << " data: " << rValue.getData() << endl;
return *this;
}
Class::Class(string n)
{
name = n;
data = 0;
cout << "name only parameterized constructor name: " << name << " data: " << data << endl;
}
Class::Class(string n, int d)
{
name = n;
data = d;
cout << "name and data parameterized constructor name: " << name << " data: " << data << endl;
}
void Class::setData(int d)
{
data = d;
}
int Class::getData() const
{
return data;
}
string Class::getName() const
{
return name;
}
const Class* const Class::pass_by_reference_using_const_reference_return_pointer(const Class& o) const
{
cout << "this is object name: " << name << " data: " << data << endl;
cout << "the ultimate const correctness nightmare" << endl;
cout << "member function of Class: pass by reference using const reference, parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by const pointer const" << endl;
return &o;
}
void pass_by_value(Class o)
{
cout << "pass_by_value:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "returns void" << endl;
}
void pass_by_reference_using_pointers(Class* o)
{
cout << "pass_by_reference_using_pointers:" << endl;
cout << "parameter is name: " << o->getName() << " data: " << o->getData() << endl;
cout << "returns void" << endl;
}
void pass_by_reference_using_non_const_reference(Class& o)
{
cout << "pass_by_reference_using_non_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "returns void" << endl;
}
void pass_by_reference_using_const_reference(const Class& o)
{
cout << "pass_by_reference_using_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "returns void" << endl;
}
Class pass_by_reference_using_const_reference_return_by_value(const Class& o)
{
cout << "pass_by_reference_using_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by value" << endl;
return o;
}
Class pass_by_reference_using_non_const_reference_return_by_value(Class& o)
{
cout << "pass_by_reference_using_non_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by value" << endl;
return o;
}
const Class* pass_by_reference_using_const_reference_return_pointer(const Class& o)
{
cout << "pass_by_reference_using_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by pointer to class const" << endl;
return &o;
}
Class* pass_by_reference_using_const_reference_return_pointer(Class& o)
{
cout << "pass_by_reference_using_non_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by pointer to non const Class" << endl;
return &o;
}
Class& pass_by_reference_using_const_reference_return_non_const_reference(Class& o)
{
cout << "pass_by_reference_using_non_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by non const reference" << endl;
return o;
}
const Class& pass_by_reference_using_const_reference_return_const_reference(const Class& o)
{
cout << "pass_by_reference_using_const_reference:" << endl;
cout << "parameter is name: " << o.getName() << " data: " << o.getData() << endl;
cout << "preparing to return by const reference" << endl;
return o;
}
int main()
{
Class default_constructed;
Class name_and_data_constructed("name_and_data_constructed", 2);
Class name_constructed("name_constructed");
default_constructed.setData(1);
name_constructed.setData(3);
cout << "Check of data in the three objects after data has been set, in order: ";
cout << default_constructed.getData() << " " << name_and_data_constructed.getData() << " " << name_constructed.getData() << endl;
cout << endl;
pass_by_value(default_constructed);
cout << endl;
pass_by_reference_using_pointers(&default_constructed);
cout << endl;
pass_by_reference_using_non_const_reference(default_constructed);
cout << endl;
pass_by_reference_using_const_reference(default_constructed);
cout << endl;
Class returned_by_value("returned_by_value");
returned_by_value = pass_by_reference_using_const_reference_return_by_value(default_constructed);
cout << "returned by value is name: " << returned_by_value.getName() << " data: " << returned_by_value.getData() << endl;
cout << endl;
Class* returned_by_pointer = pass_by_reference_using_const_reference_return_pointer(default_constructed);
cout << "returned by pointer is name: " << returned_by_pointer->getName() << " data: " << returned_by_pointer->getData() << endl;
cout << endl;
Class& returned_by_non_const_reference = pass_by_reference_using_const_reference_return_non_const_reference(default_constructed);
cout << "returned by non const reference is name: " << returned_by_non_const_reference.getName()
<< " data: " << returned_by_non_const_reference.getData() << endl;
cout << endl;
const Class& returned_by_const_reference = pass_by_reference_using_const_reference_return_const_reference(default_constructed);
cout << "returned by const reference is name: " << returned_by_const_reference.getName() << " data: " << returned_by_const_reference.getData() << endl;
cout << endl;
cout << "before simple assignment statement of: name_and_data_constructed = default_constructed" << endl;
name_and_data_constructed = default_constructed;
cout << "after simple assignment statement. name_and_data_constructed now has data " << name_and_data_constructed.getData() << endl;
cout << endl;
cout << "before complex assignment statement: name_constructed = pass_by_reference_using_non_const_reference_return_by_value(default_constructed)" << endl;
name_constructed = pass_by_reference_using_non_const_reference_return_by_value(default_constructed);
cout << "after complex assignment statement. name_constructed now has data " << name_constructed.getData() << endl;
cout << endl;
cout << "before most complex assignment statement: name_constructed = name_and_data_constructed.pass_by_reference_using_const_reference_return_by_value(default_constructed)" << endl;
name_constructed = pass_by_reference_using_const_reference_return_by_value(default_constructed);
cout << "after most complex assignment statement. name_constructed now has data " << name_constructed.getData() << endl;
cout << endl;
cout << "Check of data in the three objects after function calls, in order: ";
cout << default_constructed.getData() << " " << name_and_data_constructed.getData() << " " << name_constructed.getData() << endl;
cout << endl;
return 0;
}