c++ - 将对象转换为派生类以访问父类的 protected 成员

标签 c++ casting protected

我正在尝试访问由外部库定义和实现的类的 protected 成员。如果可能,我希望在不复制或移动实例的情况下实现这一目标。

这是一个简化的例子。假设这是来自外部库的代码:

// some_external_library.h

class Node {
    public:
        static Node Create();
    protected:
        Node(int val) : val_(val) {}
        int val_;
};

这就是我想要做的:

// my_code.cpp

#include "some_external_library.h"

Node node = Node::Create();
int val = node.val_; // <-- This is invalid since val_ is protected.

Node 类是我链接到我的程序的一些外部库的一部分。因此,我想通过添加用于访问 val_ 的公共(public)函数或友元声明来避免修改 Node 类。此外,我想避免创建 node 对象的拷贝或从中移动,因此我想避免创建派生类来移动/复制 Node 实例只是为了访问成员字段。可能吗?

我想出了一个可能的解决方案,对于最小的例子来说效果很好:

// my_code.cpp

#include "some_external_library.h"
class NodeAccessor : public Node {
    public:
        int val() const { return val_; }
};

Node node = Node::Create();
int val = static_cast<const NodeAccessor&>(node).val();

但是,我不确定这是否有效,因为 node 不是 NodeAccessor 的实例。这个标准合规吗?它会导致任何问题吗(例如,在编译外部库期间优化 val_)?

最佳答案

你做的就是UB。

在 C++ 中有一种访问私有(private)/ protected 成员的神奇方法:

ISO C++ 标准规定在显式模板实例化的情况下不进行访问检查,以下代码滥用:

template <typename Tag>
struct result
{
  using type = typename Tag::type;
  static type ptr;
};

template <typename Tag> typename result<Tag>::type result<Tag>::ptr;

template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
  /* fill it ... */
  struct filler {
    filler() { result<Tag>::ptr = p; }
  };
  static filler filler_obj;
};

template <typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;

然后

struct NodeVal { using type = int Node::*; };
template class rob<NodeVal, &Node::val_>;

最后:

int main() {
  Node node = /**/;
  (node.*result<NodeVal>::ptr);
}

Demo

关于c++ - 将对象转换为派生类以访问父类的 protected 成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57451850/

相关文章:

android - 如何从 C++ 为我的 .so 共享库调用 LoadLibrary

c++ - C/C++ 计算小数位数?

c++ - curl 在线程调用中崩溃

python - 如何将列表列表中的所有数字变成整数

c++ - 向上转换不透明指针

在 C 中将 void* 转换为 char*

java - Java中基类中父类(super class)的 protected 方法会发生什么?

c++ - 无法访问派生类中基类的 protected 成员

c++ - 在模板类中调用模板方法

java - 为什么我的分数变量在我的 GameScreen 类之外不可评估?