今天是个好日子!
属性未在 C++ 中实现。我估计我们不能写
myObject.property = value; // try to set field f_ to value
isproperty
是私有数据成员。公共数据成员违反 OOP 封装规则。
相反,我们必须编写 getter/setter 代码:
myObject.setField(value); // try to set field f_ to value
这篇文章是关于C++ 中的属性仿真。属性调用看起来像公共数据成员调用,但自定义 UDF 代码用于设置或获取真正的私有数据成员值。
我们想做的是允许简单的接口使用(像公共数据成员,没有函数调用语法),而底层的 getter/setter 可能很复杂(不仅仅是数据分配/读取)。
下面的代码(我的同事写的)展示了简单的属性实现:
#include <iostream>
template<class C, class M>
inline C* get_parent_this(typename M C::*member_ptr, M*const member_this)
{
//interpret 0 as address of parent object C and find address of its member
char* base = reinterpret_cast<char*>(nullptr);
char* member = reinterpret_cast<char*>( &(reinterpret_cast<typename C*>(base)->*member_ptr) );
//modify member_this with offset = (member - base)
return reinterpret_cast<typename C*>(reinterpret_cast<char*>(member_this) - (member - base) );
}
class Owner
{
int x,pr_y;
int get_y() {return pr_y;}
void set_y(int v) {pr_y = v;}
public:
struct
{
operator int() { return get_parent_this(&Owner::y, this)->get_y(); }
void operator =(int v) { get_parent_this(&Owner::y, this)->set_y(v); }
} y;
};
int main ()
{
Owner ow;
ow.y = 5;
std::cout << ow.y;
if( get_parent_this(&Owner::y, &ow.y) == &ow) std::cout << "OK\n";
if( (char *)&ow.y != (char *)&ow) std::cout << "OK\n";
return 0;
}
在上面的示例中有一个简单的 getter/setter 对,它不做任何额外的工作(例如完整性检查或边界检查),但此代码可能是复杂的执行边界检查、完整性检查等。这只是测试示例。
不要担心get_parent_this
帮助模板中的“奇怪”代码。最“可怕”的事情是偏移计算。nullptr (NULL, 0x0) 地址用作存根。我们不会从该地址写入或读取。我们仅将它用于基于子对象地址的所有者对象偏移量计算。我们可以使用任何地址代替 0x0。所以,这没有意义。
属性用法:
- 如果有人使用公共数据成员属性在以下情况下可能会有所帮助:1.1。如果出现错误,则跟踪公共数据成员调用;1.2. 轻松升级基于公共数据成员使用的遗留代码;
- 您如何看待 C++ 中的属性仿真?是活泼的想法吗?这个想法有缺点吗(请显示)?
- 您如何看待从子对象地址计算所有者对象地址?你知道哪些技巧和可能的陷阱?
请告诉我们你的想法!
谢谢!