C++ 17 any 类的简单模拟实现

类结构

  1. Holder 基类

    • 这是一个虚基类,用于存储任何类型的值。
    • 定义了虚析构函数、获取类型信息的虚函数type()和克隆对象的虚函数clone()
  2. PlaceHolder 模板类

    • 这是Holder的子类,用于实际存储特定类型的值。
    • 它有一个模板参数T,并包含一个类型为T的成员变量_val
    • 重写了type()clone()方法,分别返回当前存储值的类型信息和创建一个新的PlaceHolder实例。

成员变量

  • _content:一个指向Holder基类的指针,用于存储实际的值。

构造函数和析构函数

  1. 默认构造函数

    • 初始化_contentNULL
  2. 模板构造函数

    • 接受一个类型为T的值,并创建一个PlaceHolder<T>实例来存储它。
    • _content指向新创建的PlaceHolder<T>实例。
  3. 拷贝构造函数

    • 如果_content不为空,则调用clone()方法创建一个新的Holder实例。
    • _content指向新创建的Holder实例。
  4. 析构函数

    • 删除_content指向的Holder实例。

赋值运算符

  1. 模板赋值运算符

    • 接受一个类型为T的值,并创建一个临时的Any对象来存储它。
    • 使用swap方法交换当前对象和临时对象的内容。
    • 返回当前对象的引用。
  2. 拷贝赋值运算符

    • 类似于模板赋值运算符,但用于拷贝另一个Any对象。

辅助函数

  • swap:一个私有成员函数,用于交换两个Any对象的_content指针。

get 方法

  • 模板 get 方法

    • 接受一个类型参数T,并断言当前存储的类型与T一致。
    • _content强制转换为PlaceHolder<T>*类型,并返回其_val成员变量的地址。

注意事项

  1. 类型安全:通过虚函数和模板确保了类型安全。在调用get<T>()时,如果存储的类型与T不匹配,assert会触发。
  2. 资源管理:正确地管理了内存,确保了_content指向的Holder实例在不再需要时被删除。
  3. 异常安全:我没有显式处理异常,但所有操作都是基于指针和内存分配,因此可能会抛出异常(如std::bad_alloc)。在实际使用中,调用者可能需要考虑异常处理。
  4. 性能:由于使用了虚函数和动态内存分配,这个实现可能比C++17标准库中的std::any稍微慢一些。
class Any
{
    class Holder
    {
    public:
        virtual ~Holder() {}
        virtual const std::type_info &type() = 0;
        virtual Holder *clone() = 0;
    };
    template <class T>
    class PlaceHolder : public Holder
    {
    public:
        PlaceHolder(const T &val) : _val(val) {}
        ~PlaceHolder() {}
        virtual const std::type_info &type() { return typeid(T); }
        virtual Holder *clone() { return new PlaceHolder(_val); }

    public:
        T _val;
    };

private:
    Holder *_content;

private:
    void swap(Any &a)
    {
        std::swap(_content, a._content);
    }

public:
    Any() : _content(NULL) {}
    template <class T>
    Any(const T &val) : _content(new PlaceHolder<T>(val)) {}
    Any(const Any &a) : _content(a._content ? a._content->clone() : NULL) {}

    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this);
        return *this;
    }

    Any &operator=(const Any &a)
    {
        Any(a).swap(*this);

        return *this;
    }

    template <class T>
    T *get()
    {
        assert(typeid(T) == _content->type()); // 类型必须一致
        return &(((PlaceHolder<T> *)_content)->_val);
    }

    ~Any() { delete _content; }
};
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C++中,可以使用标准库中的<sys/socket.h>和<netinet/in.h>头文件来模拟socket通信。以下是一个简单的客户端和服务器端的示例代码: 服务器端代码: ```c++ #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define PORT 8080 using namespace std; int main() { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; const char *hello = "Hello from server"; // Creating socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Attaching socket to the port 8080 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Binding socket to the specified port if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } valread = read(new_socket, buffer, 1024); printf("%s\n", buffer); send(new_socket, hello, strlen(hello), 0); printf("Hello message sent\n"); return 0; } ``` 客户端代码: ```c++ #include <iostream> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define PORT 8080 using namespace std; int main(int argc, char const *argv[]) { int sock = 0, valread; struct sockaddr_in serv_addr; const char *hello = "Hello from client"; char buffer[1024] = {0}; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary form if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { printf("\nInvalid address/ Address not supported \n"); return -1; } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\nConnection Failed \n"); return -1; } send(sock, hello, strlen(hello), 0); printf("Hello message sent\n"); valread = read(sock, buffer, 1024); printf("%s\n", buffer); return 0; } ``` 这个例子中,服务器监听端口8080,客户端连接到服务器并发送“Hello from client”字符串。服务器接收到该字符串后,向客户端发送“Hello from server”字符串。 需要注意的是,这个例子中只是一个简单的示例,并没有考虑网络安全等问题。在实际的应用中,需要进行更加复杂的处理和保护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姬如祎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值