42 Common Core CPP Module 06
- Casting
- Scalar types
- Serialization
- Polimorfismoa and Run-Time Type Identification
Casting means converting a value from one type to another.
Example:
int a = 42;
float b = static_cast<float>(a); //converts int to float
-
Implicit Conversion: Performed automatically by the compiler when assigning between compatible types.
int i = 10; float f = i; //assigning an int to a float triggers an implicit conversion -
Explicit Conversion: Occurs when the programmer explicitly specifies the type conversion.
int i = 20; float f = (float)i / 10; //explicit cast using C-style casting
| Cast Type | Purpose | Check Type |
|---|---|---|
static_cast |
Safe, compile-time conversion between compatible types | Compile-time |
dynamic_cast |
Used with polymorphic classes; checks type at runtime | Runtime |
reinterpret_cast |
Reinterprets raw memory between unrelated types | Dangerous, no safety check |
const_cast |
Adds or removes const or volatile qualifiers |
Compile-time |
Used for safe, compile-time conversions between compatible types (built-in or related classes).
static_cast<type>(expression);
Example:
int i = 20;
float f = static_cast<float>(i); //convertis int to float
-
Pointer conversions between related types: "Related" means that the types share an inheritance relationship (base <-> derived). You can cast a pointer from a base class to a derived class and vice versa.
class Base {}; class Derived : public Base {}; Base* base = new Derived(); Derived *derived = static_cast<Derived*>(base); //valid: Base and Derived are related
❌ Example that does not work:
int *ptrInt = NULL;
float *ptrFloat = static_cast<float*>(ptrInt); //❌ error: types are unrelated
Used to add or remove const or volatile qualifiers.
const_cast<type>(expresion);
Example:
void aFunction(int *a)
{
std::cout << *a << endl;
}
int main()
{
int a = 10;
const int* i = &a;
aFunction(const_cast<int*>(i); //remove const to match parameter type
return (0);
}
Used for low-level reinterpreting of memory between unrelated types. It does not change the bit pattern - it just reinterprets the same memory as a different type.
reinterpret_cast<type>(expression);
Example:
struct Data
{
int id;
std::string name;
double val;
};
int main()
{
Data data = {1, "first", 30.3}
// "Serialize"
uintptr_t ptr = reinterpret_cast<uintptr_t>(data);
// "Deserialize"
Data *ptr;
ptr = reinterpret_cast<*Data>(ptr);
}
Explanation:
uintptr_tis an unsigned int type capable of storing a pointer without losing information.reinterpret_castconverts the pointer address into a numeric representation.- The conversion does not copy or transform the object, it just changes how the memory address is viewed.
- This is not real serialization: it's just pointer reinterpretation.
- When "deserializing", the integer is reinterpreted again as a pointer to the same memory address.
Used with polymorphic classes (those that have at least one virtual function). It checks the validity of a cast at runtime.
Use dynamic_cast when downcasting in polymorphic hierarchies. Never use it for unrelated or primitive types.
dynamic_cast<type>(expression);
Example with pointers:
class Base {};
class Derived : public Base {};
Base* base = new Derived();
Derived *derived = dynamic_cast<Derived*>(base); //works, derived points to Base object
Base* notBase = NULL;
Derived* fail = dynamic_cast<Derived*>(notBase); //returns NULL safely
Key point: if the pointer expression does not point to an object of type <type>, dynamic_cast returns NULL.
This is safe and does not throw exceptions.
Example with references:
Base b = new B
try
{
A& d = dynamic_cast<A&>(b); //fails because b is not A
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl; //bad_cast
}
- If the cast fails:
- Pointer version -> returns
NULL - Reference version -> throws
std::bad_cast
- Pointer version -> returns
Serialization is the process of converting an object into a form that can be stored or transmitted (e.g., into a file or over a network). The reverse process, deserialization, reconstructs the original object from that form.
In this module, you implement a single "serialization" mechanism using reinterpret_cast and uintptr_t to convert a pointer to a raw number and back.
This is not real serialization, just pointer-to-integer conversion.
In ex00, ScalarConverter is designed as a non-instantiable utility class.
-
Only the static method
ScalarConverter::convert(std::string str);should be used.
-
To prevent instantiation: constructors, destructors, and copy operations are made
private.
This ensures the class acts like a namespace and cannot be instantiated.
If it were an abstract base class, then:
- We would use a
virtualdestructor (possibly pure virtual) - Derived classes would implement the required interface
A static method beongs to the class itself, not to any specific instance.
class MyClass
{
public:
static void staticMethod();
};
int main()
{
MyClass::staticMethod(); //call withoyt creating an object
return (0);
}
Characteristics:
- No access to
this - Can only access static attributes/methods
- Only one shared instance of static members exists Use when:
- The logic does not depend on object state
- You want to group related functions inside a class
- You want shared data acress all instances
-
std::string::nposis the return value used to indicate "not found". -
Returned by any of the
find()functionsstr::string myStr = "Hello world."; if (mySrt.find('Bye') == std::string::npos) { std::cout << "Not found" << std::endl; }