C++四种类型转换cast,其在参数传递时的作用

  1. static_cast- 参数传递中的类型适配
    基本数据类型转换
cpp 复制代码
#include <iostream>

void processDouble(double d) {
    std::cout << "Processing double: " << d << std::endl;
}

void processBase(class Base* b) {
    std::cout << "Processing Base object" << std::endl;
}

int main() {
    int intValue = 42;
    
    // 在参数传递时进行static_cast:int -> double
    processDouble(static_cast<double>(intValue)); // 输出: Processing double: 42
    
    // 对比:隐式转换(也能工作,但不够明确)
    processDouble(intValue);
    
    return 0;
}

类层次结构中的上行转换

cpp 复制代码
#include <iostream>

class Base {
public:
    virtual void display() { 
        std::cout << "Base class" << std::endl; 
    }
    virtual ~Base() = default;
};

class Derived : public Base {
public:
    void display() override { 
        std::cout << "Derived class" << std::endl; 
    }
    void specificFunction() {
        std::cout << "Derived specific function" << std::endl;
    }
};

// 函数接受Base指针参数
void processObject(Base* obj) {
    obj->display(); // 多态调用
}

void processObjects(Base** objects, int count) {
    for (int i = 0; i < count; ++i) {
        objects[i]->display();
    }
}

int main() {
    Derived derivedObj;
    
    // 上行转换:Derived* -> Base*(安全)
    processObject(static_cast<Base*>(&derivedObj)); // 输出: Derived class
    
    // 在数组参数传递中的使用
    Derived* derivedArray[3];
    for (int i = 0; i < 3; ++i) {
        derivedArray[i] = new Derived();
    }
    
    // 需要将Derived**转换为Base**
    processObjects(static_cast<Base**>(derivedArray), 3);
    
    // 清理内存
    for (int i = 0; i < 3; ++i) {
        delete derivedArray[i];
    }
    
    return 0;
}
  1. dynamic_cast- 参数传递时的安全类型检查
    安全的下行转换
cpp 复制代码
#include <iostream>
#include <typeinfo>

class Animal {
public:
    virtual void speak() = 0;
    virtual ~Animal() = default;
};

class Dog : public Animal {
public:
    void speak() override {
        std::cout << "Woof!" << std::endl;
    }
    void fetch() {
        std::cout << "Fetching ball..." << std::endl;
    }
};

class Cat : public Animal {
public:
    void speak() override {
        std::cout << "Meow!" << std::endl;
    }
    void climb() {
        std::cout << "Climbing tree..." << std::endl;
    }
};

// 处理Animal参数的函数
void processAnimal(Animal* animal) {
    animal->speak();
    
    // 使用dynamic_cast进行安全的类型检查
    Dog* dog = dynamic_cast<Dog*>(animal);
    if (dog != nullptr) {
        std::cout << "It's a Dog! ";
        dog->fetch();
    }
    
    Cat* cat = dynamic_cast<Cat*>(animal);
    if (cat != nullptr) {
        std::cout << "It's a Cat! ";
        cat->climb();
    }
}

// 使用引用参数的版本(失败时抛出异常)
void processAnimalRef(Animal& animal) {
    try {
        Dog& dog = dynamic_cast<Dog&>(animal);
        std::cout << "Definitely a Dog! ";
        dog.fetch();
    }
    catch (const std::bad_cast& e) {
        // 不是Dog,继续检查Cat
        try {
            Cat& cat = dynamic_cast<Cat&>(animal);
            std::cout << "Definitely a Cat! ";
            cat.climb();
        }
        catch (const std::bad_cast& e) {
            std::cout << "Unknown animal type" << std::endl;
        }
    }
}

int main() {
    Dog dog;
    Cat cat;
    
    std::cout << "=== Processing Dog ===" << std::endl;
    processAnimal(&dog);
    
    std::cout << "\n=== Processing Cat ===" << std::endl;
    processAnimal(&cat);
    
    std::cout << "\n=== Using reference version ===" << std::endl;
    processAnimalRef(dog);
    processAnimalRef(cat);
    
    return 0;
}
  1. const_cast- 参数传递中的常量性修改
    调用旧式API的兼容性处理
cpp 复制代码
#include <iostream>
#include <cstring>

// 旧式C函数,参数是非const的(但实际不会修改)
void legacyCFunction(char* buffer) {
    // 这个函数声明时没有用const,但实际是只读的
    std::cout << "Legacy function processing: " << buffer << std::endl;
}

// 现代C++函数,正确使用const
void modernFunction(const char* buffer) {
    std::cout << "Modern function processing: " << buffer << std::endl;
    
    // 需要调用旧式API,但旧API需要非const参数
    // 使用const_cast来移除const(因为我们知道legacyCFunction不会修改数据)
    legacyCFunction(const_cast<char*>(buffer));
}

// 重载函数示例
class Logger {
public:
    // const版本
    void log(const std::string& message) const {
        std::cout << "LOG: " << message << std::endl;
    }
    
    // 非const版本,内部需要修改一些缓存但对外表现是const的
    void log(const std::string& message) {
        // 在非const版本中调用const版本以避免代码重复
        const_cast<const Logger*>(this)->log(message);
        // 然后可以执行一些非const的操作
        updateCache();
    }
    
private:
    void updateCache() {
        // 更新一些内部缓存
        std::cout << "Updating cache..." << std::endl;
    }
};

// 错误示例:修改真正的const对象
void dangerousExample() {
    const int immutable = 100;
    const int* constPtr = &immutable;
    
    // 危险!未定义行为!
    int* dangerousPtr = const_cast<int*>(constPtr);
    *dangerousPtr = 200; // 这可能导致程序崩溃或不可预测行为
    
    std::cout << "immutable = " << immutable << std::endl; // 可能还是100!
    std::cout << "*dangerousPtr = " << *dangerousPtr << std::endl; // 可能是200
}

int main() {
    const char* message = "Hello, World!";
    
    std::cout << "=== Safe const_cast usage ===" << std::endl;
    modernFunction(message);
    
    std::cout << "\n=== Logger example ===" << std::endl;
    Logger logger;
    const Logger constLogger;
    
    logger.log("Non-const logger");        // 调用非const版本
    constLogger.log("Const logger");       // 调用const版本
    
    std::cout << "\n=== Dangerous example (未定义行为) ===" << std::endl;
    // dangerousExample(); // 取消注释会导致未定义行为
    
    return 0;
}
  1. reinterpret_cast- 底层数据重新解释
    序列化和网络编程中的应用
cpp 复制代码
#include <iostream>
#include <cstring>
#include <cstdint>

// 网络数据包结构
struct NetworkPacket {
    uint32_t header;
    uint16_t dataLength;
    char payload[100];
};

// 序列化函数:将对象转换为字节流
template<typename T>
void serializeToBytes(const T& obj, char* buffer) {
    // 使用reinterpret_cast将对象指针转换为char指针进行字节操作
    const char* bytePtr = reinterpret_cast<const char*>(&obj);
    std::memcpy(buffer, bytePtr, sizeof(T));
}

// 反序列化函数:将字节流转换回对象
template<typename T>
T deserializeFromBytes(const char* buffer) {
    T obj;
    char* bytePtr = reinterpret_cast<char*>(&obj);
    std::memcpy(bytePtr, buffer, sizeof(T));
    return obj;
}

// 函数指针类型转换(跨DLL边界等场景)
typedef void (*SimpleFunction)();
typedef int (*ComplexFunction)(int, double);

void simpleFunc() {
    std::cout << "Simple function called" << std::endl;
}

int complexFunc(int a, double b) {
    std::cout << "Complex function: " << a << ", " << b << std::endl;
    return a + static_cast<int>(b);
}

// 回调函数处理(模拟系统API)
void registerCallback(void* callback, int type) {
    if (type == 0) {
        SimpleFunction func = reinterpret_cast<SimpleFunction>(callback);
        func();
    } else {
        ComplexFunction func = reinterpret_cast<ComplexFunction>(callback);
        int result = func(10, 3.14);
        std::cout << "Callback result: " << result << std::endl;
    }
}

// 危险示例:错误的类型重新解释
void dangerousReinterpret() {
    double d = 3.14159;
    std::cout << "Original double: " << d << std::endl;
    
    // 将double*重新解释为int*
    int* intPtr = reinterpret_cast<int*>(&d);
    std::cout << "First 4 bytes as int: " << *intPtr << std::endl;
    
    // 这是极度危险的!违反了严格别名规则
    *intPtr = 0; // 可能破坏double的内存表示
    std::cout << "Corrupted double: " << d << std::endl; // 未定义行为!
}

int main() {
    std::cout << "=== 序列化/反序列化示例 ===" << std::endl;
    
    NetworkPacket originalPacket{0x12345678, 50, "Hello Network!"};
    char buffer[sizeof(NetworkPacket)];
    
    serializeToBytes(originalPacket, buffer);
    
    NetworkPacket restoredPacket = deserializeFromBytes<NetworkPacket>(buffer);
    std::cout << "Header: 0x" << std::hex << restoredPacket.header 
              << ", Data: " << restoredPacket.payload << std::dec << std::endl;
    
    std::cout << "\n=== 函数指针转换示例 ===" << std::endl;
    
    // 注册不同类型的回调函数
    registerCallback(reinterpret_cast<void*>(simpleFunc), 0);
    registerCallback(reinterpret_cast<void*>(complexFunc), 1);
    
    std::cout << "\n=== 指针和整数转换示例 ===" << std::endl;
    
    int value = 42;
    int* ptr = &value;
    
    // 将指针转换为整数(用于存储或传输)
    uintptr_t intValue = reinterpret_cast<uintptr_t>(ptr);
    std::cout << "Pointer as integer: " << intValue << std::endl;
    
    // 将整数转换回指针
    int* restoredPtr = reinterpret_cast<int*>(intValue);
    std::cout << "Restored pointer value: " << *restoredPtr << std::endl;
    
    std::cout << "\n=== 危险示例(注释掉) ===" << std::endl;
    // dangerousReinterpret(); // 取消注释会导致未定义行为
    
    return 0;
}
相关推荐
kyle~2 小时前
C++---万能指针 void* (不绑定具体数据类型,能指向任意类型的内存地址)
开发语言·c++
誰能久伴不乏2 小时前
Linux 进程通信与同步机制:共享内存、内存映射、文件锁与信号量的深度解析
linux·服务器·c++
_F_y2 小时前
C++异常
c++
小龙报2 小时前
《算法通关指南:算法基础篇 --- 一维前缀和 — 1. 【模板】一维前缀和,2.最大子段和》
c语言·数据结构·c++·算法·职场和发展·创业创新·visual studio
郝学胜-神的一滴3 小时前
Effective STL 第9条:C++容器元素删除技巧详解
开发语言·c++·程序人生·stl
Ma_Hong_Kai3 小时前
带复选框的combox
c++·mfc
syker4 小时前
太极指令集架构(TCIS)v1.1与主流指令集比较研究报告
c++·架构
jf加菲猫5 小时前
第1章 认识Qt
开发语言·c++·qt·ui
蒋星熠7 小时前
全栈开发实战指南:从架构设计到部署运维
运维·c++·python·系统架构·node.js·devops·c5全栈