派生类如何使用基类的受保护成员?

时间:2018-03-28 15:10:20

标签: c++ protected private-members

假设基类A定义了受保护的成员。派生类B使用此成员。

class A
{
public:
  A(int v) : value(v) { }

protected:
  int value;
};

class B : public A
{
public:
  B(int v) : A(v) { }
  void print() const;
  void compare_and_print(const A& other) const;
};

函数B::print只取当前成员的值并打印出来:

void B::print() const
{
  std::cout << "Value: " << value << "\n";
}

另一个成员函数B::compare_and_print采用A的实例,检查它们的值并打印两者的最大值:

void B::compare_and_print(const A& other) const
{
  auto max_value = std::max(value, other.value);
  std::cout << "Max value: " << max_value << "\n";
}

如果other是类B的实例,那就没问题了。但该函数希望与任何类型的A实例一起使用。遗憾的是,这不会编译。这就是clang对此所说的:

test.cpp:27:42: error: 'value' is a protected member of 'A'
  auto max_value = std::max(value, other.value);
                                         ^
test.cpp:9:7: note: can only access this member on an object of type 'B'
  int value;
      ^
1 error generated.

这种限制听起来与我相反。但是,我不会对C ++标准提出异议(我对这个决定背后的理由感兴趣)。

我的问题是在我的项目中我确实有这种用例:派生类有一个方法,它接受基类的一个实例,需要访问被接收对象的受保护成员。

最简单的解决方案是我当前实现的解决方案,是将一个公共成员函数添加到基类,该基类返回受保护的成员。这个解决方案并不能完全满足我,因为我想避免以这种方式导出成员。

如何通过派生类启用基类'受保护成员的使用而不通过API导出成员?

编辑: 一些相关的问题是:

我想要的答案是解释此问题的设计模式的解释,而不将受保护的成员暴露给外部代码(其中外部意味着,代码不属于定义这些类的框架。)

我承认,这种模式可能不存在。

2 个答案:

答案 0 :(得分:3)

实际上存在使用成员指针的漏洞(没有强制转换,没有复制):

void B::compare_and_print(const A& other) const
{
  auto max_value = std::max(value, other.*(&B::value));
  std::cout << "Max value: " << max_value << "\n";
}

答案 1 :(得分:0)

您可以使用辅助结构绕过受保护的结构:

A_Helper::GetProtectedValue(a)

您可以在other

的任何地方使用它

在您的情况下,您可以将const B&投射到static_cast(通过reinterpret_castother),但您不知道B的实例是否为other类型为B。有了这个值,读取代码的人会认为B的类型为value_B,并且可能会插入导致读取/写入“随机”内存的代码。

考虑班级other有另一个成员Cstatic_cast<const B&>(other).value_B属于ID | COL1 | COL2 | COL3 | COL4 | COL5 | --------------------------------------- 1 | 8 | 35 | 42 | 12 | 27 | 2 | 22 | 42 | 35 | 8 | NULL | 3 | 18 | 22 | 8 | NULL | NULL | 4 | 42 | 12 | 27 | 35 | 8 | 5 | 18 | 27 | 12 | 22 | NULL | 类型。使用ID | Item| 1 | 8 | 1 | 35 | 1 | 42 | . | . | . | . | . | . | 是未定义的行为。