2-9) Casting and Type identification


Type Definition

 

typedef unsigned long ulong;

ulong ul; // Equivalent to "unsigned long ul;"

 

typedef struct mystructtag

{

   int i;

   float f;

   char c;

} mystruct;

 

mystruct ms; // Equivalent to "struct mystructtag ms;"

 

typedef int (*funcptr)(); // funcptr is synonym for "pointer

// to function taking no parameters and returning int"

 

funcptr table[10]; // Equivalent to "int (*table[10])();"


 



User defined conversions: Constructors and Conversion Operators
 

#include <iostream>

#include <cstring>

using namespace std;

 

class String {

public:

   String(const char * string) : buffer(string) {}

   operator int (void) {return strlen(buffer);} //TYPE CONVERSION OPERATOR

   void print() {cout << buffer << '\n';}

private:

   const char * buffer;

};

 

int main() {

   char * ptr = "abcd";

   String s = ptr; //char * to String conversion

   s.print();

   int i = s; //String to int conversion

   cout << "integer is " << i << '\n';

   return 0;

}

 

/* OUTPUT

abcd

integer is 4

*/



User Defined Conversions:
Here an B is converted to an A through an A class constructor, A(B&)

#include <iostream>

using namespace std;

 

class B;

class A{

public:

   A() {}

   A(B & b) {cout << "A(B) constructor \n";} //constructor

};

 

class B{

public:

   operator A() {

      cout << "operator A() \n";

      return A();} //conversion operator

};

 

int main() {

   B b;

   A a = b; // A(B) constructor is called

   return 0;

}

/*OUTPUT

A(B) constructor

*/



User Defined Conversions: Here a B is converted to an A through an conversion operator in class B. Notice the A(B) constructor is commented out, since it would be preferred by the compiler.
 

#include <iostream>

using namespace std;

 

class B;

class A{

public:

   A() {}

   //A(B & b) {cout << "A(B) constructor \n";} //constructor

};

 

class B{

public:

   operator A() {

      cout << "operator A() \n";

      return A();} //conversion operator

};

 

int main() {

   B b;

   A a = b; // A(B) constructor is called

   return 0;

}

/*OUTPUT

operator A()

*/




without explict keyword
 

#include <iostream>

using namespace std;

 

class String {

friend ostream & operator<<(ostream & os, const String & str);

public:

   String (int len=20) { //<------no keyword explicit

   cout << "string length is " << len << "\n";

   buffer = new char[len];

}

private:

   char * buffer;

};

ostream & operator<<(ostream & os, const String & str){

   os << str.buffer;

   return os;

}

int main() {

   cout << "creating string" << endl;

   String s = 'c'; //equivalent to String s = String(99);

   cout << s << endl;

   return 0;

}

 

/* OUTPUT

creating string

string length is 99

様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様

様様様様様様様様様猷臆課

*/


 



Suppressing Implicit Type Conversion with explicit

#include <iostream>

using namespace std;

 

class String {

friend ostream & operator<<(ostream & os, const String & str);

public:

   explicit String (int len=20) { //<------no keyword explicit

   cout << "string length is " << len << "\n";

   buffer = new char[len];

}

private:

   char * buffer;

};

ostream & operator<<(ostream & os, const String & str){

   os << str.buffer;

   return os;

}

int main() {

   cout << "creating string" << endl;

   String s = 'c'; //<----COMPILE ERROR;

   cout << s << endl;

   return 0;

}

 


 

Casting and Constructors

A cast will invoke a constructor for user defined types (classes)
 

#include <iostream>

using namespace std;

 

class Date {

public:

   Date ( ):day(0), month(0), year(0) { cout << "Date()" << endl; }

   Date (int d, int m, int y ):day(d), month(m), year(y) { cout << "Date(int,int,int)" << endl; }

   Date (const Date & d ): day(d.day), month(d.month), year(d.year) { cout << "Date(const Date &)" << endl; }

private:

   int day, month, year;

};

 

class Person {

public:

   Person ( ):name("unknown") { cout << "Person()" << endl; }

   Person (char * aName ):name(aName) { cout << "Person(char*)" << endl; }

   Person (const Person & p ):name(p.name) { cout << "Person(const Person &)" << endl; }

   Person (Date & d) : name("unkown"), birthday(d) {cout << "Person(Date&)" << endl;}

private:

   char * name;

   Date birthday;

};

 

void main() {

   Person lou("Lou");

   Date d(12,12,2008);

   lou = (Person) d; //same as lou = Person(d);

}

 

/*OUTPUT

Date()

Person(char*)

Date(int,int,int)

Date(const Date &)

Person(Date&)

*/



Example using String class

 

#include <iostream>

#include <cstring>

using namespace std;

 

class String {

public:

   String(const char * string) {

      cout << "String(char*)\n";

      length = strlen(string);

      buffer = new char[strlen(string) + 1];

      strcpy(buffer, string);

   }

 

   String(int len) {

       cout << "String(int)\n";

       length = len;

       buffer = new char[length+1];

       for(int i= 0; i<length; i++)

         buffer[i] = 'C';

       buffer[length] = '\0'; //null character

   }

 

   String(const String & s) {

      cout << "String(String &)";

      length = s.length;

      buffer = new char[length+1];

      for(int i= 0; i<length+1; i++)

         buffer[i] = s.buffer[i];

   }

 

   operator int (void) {cout << "operator: int\n";

      return length;

   }

   void print(ostream & o) const {o << buffer << '\n';}

private:

   char * buffer;

   int length;

};

 

ostream & operator<<(ostream & out, const String & s){

    s.print(out);

    return out;

}

 

int main() {

   char * ptr = "abcd";

   String s = ptr; //char * to String conversion

   String s2 = 5; //int to String conversion

   cout << s << s2;

   int i = s; //String to int conversion

   cout << "integer is " << i << '\n';

   return 0;

}

 

/*OUTPUT

String(char*)

String(int)

abcd

CCCCC

operator: int

integer is 4

*/





Illustration of dynamic casting and type identification

#include<iostream.h>
#include<typeinfo>

//must enable rtti
//in VC 6.00 Project->Settings->C/C++

class B {
public:
 virtual ~B() {}
};

class D : public B {
public:
 virtual void bar() {cout << "run bar() \n";}
};
template <class T>
void foo(B& ref_B) {
  cout << "running foo\n";
  try{
   cout << "running foo<" <<
    typeid(T).name() << ">("
    << typeid(ref_B).name() << ")\n";

  D& ref_D = dynamic_cast<D&>(ref_B);
  ref_D.bar();
  }
  catch(...) {
   cout << "caught exception\n";
  }
}
int main() {
 D arg;
 foo<int>(arg);
 return 0;
}

/*
running foo<int>(class D)
run bar()
*/