我正在尝试访问由外部库定义和实现的类的 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);
}
关于c++ - 将对象转换为派生类以访问父类的 protected 成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57451850/