// test_safe1.cpp first of sequence, shows UNsafe // test_safe2.cpp adds copy constructor, 'explicit' // AND operator= // all three are needed to be safe !!! #include using namespace std; int main() { cout << "test_safe1.cpp is unsafe" << endl; class unsafe1 { public: unsafe1(){i=1; a=0;} unsafe1(unsafe1 & x){*this = x;} ~unsafe1(){delete a;} void set(int ii){i=ii;} int get(){return i;} void set(int *aa){a=aa;} void set(int index, int val){ *(a+index)=val;} int get(int index){return *(a+index);} private: int i; // single variables OK int *a; // bad news, pointer (array) }; int d1[3]={1, 2, 3}; unsafe1 U1; unsafe1 U2; try{ cout << "illegal index" << U1.get(1) << endl; }catch(...){cout << "caught illegal index." << endl;} U1.set(d1); cout << "index 1 of U1 is 2== " << U1.get(1) << endl; U2=U1; // copies bits BAD, should build a copy cout << "index 1 of U2 is 2== " << U2.get(1) << endl; unsafe1 U3 = U1; // copies bits BAD, should use 'explicit' cout << "index 1 of U3 is 2== " << U3.get(1) << endl; unsafe1 U4(U1); // copies bits BAD, should use copy constructor cout << "index 1 of U4 is 2== " << U4.get(1) << endl; cout << "now U1.set(1,5) changes U2, U3 and U4 also !!!" << endl; U1.set(1,5); // set index 1 to value 5 cout << "index 1 of U1 is 5== " << U1.get(1) << endl; cout << "index 1 of U2 is 2== " << U2.get(1) << " BAD" << endl; cout << "index 1 of U3 is 2== " << U3.get(1) << " BAD" << endl; cout << "index 1 of U4 is 2== " << U4.get(1) << " BAD" << endl; cout << "end test_safe1" << endl; return 0; } //Output from executing program // test_safe1.cpp is unsafe // caught illegal index. // index 1 of U1 is 2== 2 // index 1 of U2 is 2== 2 // index 1 of U3 is 2== 2 // index 1 of U4 is 2== 2 // now U1.set(1,5) changes U2, U3 and U4 also !!! // index 1 of U1 is 5== 5 // index 1 of U2 is 2== 5 BAD // index 1 of U3 is 2== 5 BAD // index 1 of U4 is 2== 5 BAD // end test_safe1