【问题标题】:C++ conversion: have pointer to object member, calculate pointer to objectC++转换:有指向对象成员的指针,计算指向对象的指针
【发布时间】:2014-01-02 01:07:15
【问题描述】:

C++ 有static_castbase_class_pointer 转换为derived_class_pointer

object_data_member_pointer转换为object_pointer的操作非常相似。

我使用不安全的 C 类型转换编写了函数 ConvertDataMemberPtrToObjectPtr

  • 如何以安全的方式做到这一点?成员的链接必须指定为模板参数member_ptr
  • 如果使用这样的实现会不会有什么问题?

来源:

#include <stdio.h>
#include <tchar.h>

template< class T, class Member_type, Member_type T::*member_ptr >
inline T *ConvertDataMemberPtrToObjectPtr(Member_type& member) {    
    //Got reference to member 'member' of object 'T', return pointer to object 'T'
    // obj_ptr = member_ptr - offset_of_member_field
    return (T*) ( ((char*)(&member)) - ( (char*) (  &( ((T*)(0))->*member_ptr ) )  ) );
}

struct Test {
    int a;
    int b;
};

int _tmain(int argc, _TCHAR* argv[]) {

    Test obj;

    printf("\n0x%08lX", ConvertDataMemberPtrToObjectPtr<Test,int,&Test::a>(obj.a));
    printf("\n0x%08lX", ConvertDataMemberPtrToObjectPtr<Test,int,&Test::b>(obj.b));

    // This is must be avoided when using ConvertDataMemberPtrToObjectPtr!!!
    printf("\n0x%08lX - error!", ConvertDataMemberPtrToObjectPtr<Test,int,&Test::a>(obj.b));

    return 0;
}

使用父母代替成员和static_cast

template <class T, int id=0>
class Link {
public:
    int value;
    T *GetObjectPtr() { return static_cast<T*>(this); }
};
enum MyLinkId { Main=0, Red=1 };
class MyItem : public Link<MyItem,Main>, public Link<MyItem,Red> {};

MyItem x;
Link<MyItem,Main> *p2 = &x;
Link<MyItem,Red> *p3 = &x;

printf("\n0x%08lX", p2->GetObjectPtr());
printf("\n0x%08lX", p3->GetObjectPtr());

【问题讨论】:

  • 既然有obj,为什么不直接使用呢?如果你不能在你的真实代码中,那么丑陋的演员是你唯一的手段。
  • 我考虑了模板中描述的情况。我认为这种转换有时会很有用。在我的问题中,我决定使用多重继承和static_cast
  • 通过 MyItem 访问值会模棱两可!
  • 是的。 int value 对于链接必须是私有的。

标签: c++ pointers static-cast member-pointers pointer-conversion


【解决方案1】:

您要达到的目标是不可能的:缺少区分成员的信息。 您需要一个唯一的引用成员,您可以将其传递给您的转换函数。

struct UniqueReferenceMember {};
struct Test {
    UniqueReferenceMember unique_reference_member;
    int a;
    int b;
};

不过,这样做毫无意义。有对象指针,可以直接传(可能转成void*);

【讨论】:

  • 我想避免return (T*)... 中的“不安全的 C 类型转换”。在我看来,您对printf("\n0x%08lX - error!"... 问题的回答似乎不是我的意思。
  • 不 - 我正在解决您试图区分成员的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 2016-02-25
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多