C++:自定义 vtable 实现不起作用

问题描述

我正在尝试实现自定义 vtable 以更好地理解虚拟表和覆盖的概念。为此,我有以下“基础”类

#pragma once

#include <iostream>
#include <string>

using namespace std::string_view_literals;

struct vtable;

class IdentityDocument {
public:
    IdentityDocument()
        : vtable_ptr_(&IdentityDocument::VTABLE),unique_id_(++unique_id_count_)
    {
        std::cout << "IdentityDocument::Ctor() : "sv << unique_id_ << std::endl;
    }

    ~IdentityDocument() {
        --unique_id_count_;
        std::cout << "IdentityDocument::Dtor() : "sv << unique_id_ << std::endl;
    }

    IdentityDocument(const IdentityDocument& other)
        : vtable_ptr_(other.vtable_ptr_),unique_id_(++unique_id_count_)
    {
        std::cout << "IdentityDocument::CCtor() : "sv << unique_id_ << std::endl;
    }

    IdentityDocument& operator=(const IdentityDocument&) = delete;

    void PrintID() const {
        std::cout << "IdentityDocument::PrintID() : "sv << unique_id_ << std::endl;
    }

    static void PrintUniqueIDCount() {
        std::cout << "unique_id_count_ : "sv << unique_id_count_ << std::endl;
    }

    int GetID() const {
        return unique_id_;
    }

private:
    vtable* vtable_ptr_ = nullptr;

    static int unique_id_count_;
    static vtable VTABLE;
    int unique_id_;
};

struct vtable
{
    void (IdentityDocument::* const PrintID)() const;

    vtable (
        void (IdentityDocument::* const PrintID)() const
    ) : PrintID(PrintID) {}
};

int IdentityDocument::unique_id_count_ = 0;
vtable IdentityDocument::VTABLE = {&IdentityDocument::PrintID};

这是另一个必须覆盖 PrintId 方法的类

#pragma once

#include "identity_document.h"
#include <iostream>
#include <string>
#include <ctime>

using namespace std::string_view_literals;

class Passport {
public:
    Passport()
        : expiration_date_(GetExpirationDate())
    {
        IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
        vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
        vtable_ptr = &Passport::VTABLE;

        std::cout << "Passport::Ctor()"sv << std::endl;
    }

    Passport(const Passport& other)
        : identity_(other.identity_),expiration_date_(other.expiration_date_)
    {
        IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
        vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
        vtable_ptr = &Passport::VTABLE;

        std::cout << "Passport::CCtor()"sv << std::endl;
    }

    ~Passport() {
        std::cout << "Passport::Dtor()"sv << std::endl;
    }

    void PrintID() const {
        std::cout << "Passport::PrintID() : "sv << identity_.GetID();
        std::cout << " expiration date : "sv << expiration_date_.tm_mday << "/"sv << expiration_date_.tm_mon << "/"sv
                  << expiration_date_.tm_year + 1900 << std::endl;
    }

    void PrintVisa(const std::string& country) const {
        std::cout << "Passport::PrintVisa("sv << country << ") : "sv << identity_.GetID() << std::endl;
    }

private:
    IdentityDocument identity_;
    const struct tm expiration_date_;
    static vtable VTABLE;

    tm GetExpirationDate() {
        time_t t = time(nullptr);
        tm exp_date = *localtime(&t);
        exp_date.tm_year += 10;
        mktime(&exp_date);
        return exp_date;
    }
};

vtable Passport::VTABLE = {reinterpret_cast<void (IdentityDocument::*)() const>(&Passport::PrintID)};

还有一个简短的演示:

int main() {
    array<IdentityDocument*,1> docs = { (IdentityDocument*)(new Passport()) };
    for (const auto* doc : docs) {
        doc->PrintID();
    }
}

不幸的是,我看到未调用“派生”方法。我是否使用了错误的方法来实现 vtable 概念?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)