当一个对象不是派生类时,滥用interpret_cast将其转换为派生类可以吗
is it ok to abuse reinterpret_cast to convert an object to a derive class when it is not?
以下代码正确编译并工作,使我能够访问类的受保护字段。但是这样做可以吗?感觉很脏,但我从Java中知道什么:
#include <iostream>
class Base {
public:
Base() : _f(42) {
}
int getF() { return _f; }
protected:
int _f;
};
class Der : public Base {
public:
void setF(int f) { _f = f; }
};
int main(int argc, char ** argv) {
Base *b = new Base();
std::cout << b->getF() << std::endl;
Der *d = reinterpret_cast<Der*>(b);
d->setF(37);
std::cout << b->getF()<< std::endl;
}
如果我是对的,但这不好,那么有什么好方法可以公开对象的内部封装数据字段,这些字段通常不需要修改,但在测试中确实需要更改?实例是在其他组件内部创建的,因此更改其类型并非易事。
否,如果您假设一个对象的类型为Der
,而它不是,则行为是未定义的。这可能会在运行时失败,而且非常严重。除了通常的情况(特别是请求编译器使无效代码崩溃)之外,如果编译器的优化器假设由于您将其强制转换为Der*
,那么它的类型必须是Der
,那么这可能会在运行时失败。如果随后调用虚拟函数,编译器可能会认为,由于动态类型已被称为Der
,因此可以优化虚拟方法查找。
如果我是对的,但这不好,那么有什么好方法可以公开对象的内部封装数据字段,这些字段通常不需要修改,但在测试中确实需要更改?
friend
关键字似乎适用于此。此关键字使类的私有(和受保护)成员在类之外可用。由于Base
类应该知道哪个类或函数将对其进行单元测试,因此它可以授予对该类或函数的访问权限。
class Base {
friend class BaseTester;
// ...
protected:
int _f;
};
class BaseTester {
public:
static void test() {
Base *b = new Base();
b->_f = 37;
}
};
int main(int argc, char ** argv) {
BaseTester::test();
}
为了完整性,如果出于某种原因无法修改Base
,C++的访问检查中有一些漏洞可能会被滥用。这里有一个:
#include <iostream>
class Base {
// ...
protected:
int _f;
};
class BaseHack : public Base {
public:
static constexpr int Base::*_f = &BaseHack::_f;
};
int main(int argc, char ** argv) {
Base *b = new Base();
b->*BaseHack::_f = 37;
}
在BaseHack
中,表达式&BaseHack::_f
是允许的,因为它命名了通过自己的类访问的基类的受保护成员。但由于_f
实际上是在类Base
中定义的,所以它的类型是int Base::*
而不是int BaseHack::*
,并且没有规则阻止它用于访问Base
的成员。
相关文章:
- 存储模板类型以强制转换回派生<T>
- 在 C++ 中将对象转换为派生类型
- 从基类实例调用派生类方法而不进行强制转换
- 从基指针到派生的强制转换问题
- C++将派生类转换为基类时'object slicing'期间发生的情况
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 为什么从基转换为派生提供此功能?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 从从该抽象类派生的 Python 对象强制转换C++抽象类C++
- 基类到派生类的强制转换向量
- 有没有办法复制派生类指针的向量而不将其强制转换为基类?
- 为什么此代码不将基类强制转换为 c++ 中的派生类?
- 如何在运行时将指向派生类的 void* 正确转换为指向基类的 void*
- 从基类的共享指针向下转换到派生类的引用
- 为了访问方法,从基类动态转换为派生类
- 如何将矢量<派生*>转换为矢量<Base*时避免复制>