MST

星途 面试题库

面试题:C++类外访问非公有成员的底层原理及特殊场景应用

在C++中,我们知道类的非公有成员通常不能在类外直接访问。但在某些特殊的库开发场景下,可能需要在类外有限制地访问非公有成员。例如,一个用于性能分析的库,需要偶尔获取类内部的一些非公有状态变量来进行深度分析。假设我们不能修改类的原始定义(即不能将非公有成员改为公有),请阐述一种通过模板元编程或其他高级技术手段实现这种有限制访问的思路,并给出关键代码示例及对其原理的详细解释。
39.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 使用友元类结合模板元编程思路

  • 思路
    • 定义一个模板友元类,这个友元类专门用于访问目标类的非公有成员。由于友元关系的存在,友元类可以访问目标类的非公有成员。同时利用模板元编程的特性,可以对访问进行更细粒度的控制,比如只在特定条件下才允许访问。
  • 关键代码示例
// 定义目标类
class TargetClass {
private:
    int privateVariable;
public:
    TargetClass(int value) : privateVariable(value) {}
    // 模板友元类声明
    template <typename T>
    friend class Accessor;
};

// 模板友元类定义
template <typename T>
class Accessor {
public:
    static int getPrivateVariable(T& target) {
        return target.privateVariable;
    }
};
  • 原理解释
    • TargetClass中,声明了template <typename T> friend class Accessor;,这使得Accessor模板类成为TargetClass的友元。友元关系赋予了Accessor类访问TargetClass非公有成员的权限。
    • Accessor模板类中的getPrivateVariable静态成员函数,通过接受TargetClass类型的引用,能够访问其privateVariable成员。由于Accessor是模板类,还可以通过模板参数进一步定制化访问逻辑,比如根据不同的模板参数执行不同的访问策略,从而实现有限制的访问。

2. 使用CRTP(Curiously Recurring Template Pattern)思路

  • 思路
    • 利用CRTP,让目标类继承自一个模板类,在模板类中定义访问目标类非公有成员的接口。这样既不需要修改目标类的非公有成员属性,又能在模板类层次实现对非公有成员的访问。
  • 关键代码示例
// 模板基类
template <typename Derived>
class BaseAccessor {
public:
    int getPrivateVariable() {
        return static_cast<Derived*>(this)->privateVariable;
    }
};

// 目标类继承自模板基类
class TargetClass : public BaseAccessor<TargetClass> {
private:
    int privateVariable;
public:
    TargetClass(int value) : privateVariable(value) {}
};
  • 原理解释
    • TargetClass继承自BaseAccessor<TargetClass>,利用CRTP的特性,BaseAccessor中的成员函数可以通过static_cast<Derived*>(this)this指针转换为派生类指针,从而访问派生类(即TargetClass)的非公有成员privateVariable。这种方式在不改变TargetClass非公有成员访问属性的前提下,实现了在BaseAccessor层次对TargetClass非公有成员的访问,达到了有限制访问的目的。