// Remove "x" to invoke feature.
#define xTEST_BAD_ASSIGN
#if defined( CPP11 )
# define OVERRIDE override
# define NOEXCEPT noexcept
#else
# define OVERRIDE
# define NOEXCEPT throw()
#endif
//---------------------------------------------------------------------------
#include <assert.h> // assert
#include <algorithm> // std::swap
#include <exception> // std::terminate
#include <string> // std::string
#include <iostream> // std::wcout, std::wcerr, std::endl
using namespace std;
#define FATAL_ERROR( s ) \
assert( !s ); wcerr << s << endl; terminate();
class Person
{
private:
string name_;
public:
string name() const { return name_; }
virtual void swapWith( Person& other ) NOEXCEPT
{
using std::swap; swap( name_, other.name_ );
}
void operator=( Person other ) { swapWith( other ); }
Person( string const& name )
: name_( name )
{}
};
class Student
: public Person
{
private:
int studentId_;
virtual void swapWith( Person& ) NOEXCEPT OVERRIDE
{
FATAL_ERROR( "Student::swapWith( Person& ): dest. value slicing" );
}
public:
int studentId() const { return studentId_; }
virtual void swapWith( Student& other ) NOEXCEPT
{
Person::swapWith( other );
using std::swap; swap( studentId_, other.studentId_ );
}
void operator=( Student other ) { swapWith( other ); }
Student( string const& name, int const studentId )
: Person( name ), studentId_( studentId )
{}
};
wostream& operator<<( wostream& stream, string const& s )
{
return (stream << s.c_str());
}
int main()
{
Person a( "Hillary Clinton" );
Student b1( "John Smith", 12345 );
Student b2( "Mary Jones", 88888 );
Person& bAsPerson = b1; // OK.
wcout
<< "Name: " << b1.name()
<< ". Student id: " << b1.studentId() << "."
<< endl;
#ifdef TEST_BAD_ASSIGN
bAsPerson = a; // Terminates at run-time (i.e. crash).
#else
b1 = b2; // Good/allowed assignment.
#endif
wcout
<< "Name: " << b1.name()
<< ". Student id: " << b1.studentId() << "."
<< endl;
}