English 中文(简体)
特殊类别 这是安全的,跨越图书馆边界
原标题:
  • 时间:2009-05-28 18:22:58
  •  标签:

如果C++不是我的主要语言,我将不胜感激。

我有一个模范班,来自多个图书馆。 我试图拿出一种办法,以独一无二地向每个衍生阶级分配id。 我需要能够用静态的方法,例如,这样做。


template < class DERIVED >
class Foo
{
public:
    static int s_id()
    {
        // return id unique for DERIVED
    }
    // ...
};
Thank you!
最佳回答

在此,我结束了这项工作。 如果你有任何反馈(建议、意见),请让我知道。


template < class DERIVED >
class Foo
{
public:
    static const char* name(); // Derived classes will implement, simply
// returning their class name static int s_id() { static const int id = Id_factory::get_instance()->get_id(name()); return id; } // ... };

基本上,在进行细微比较而不是点比较之后将分配补贴。 就速度而言,这并不理想,但我只是id静的静脉,因此只能计算每个发展经济学所一次。

问题回答

几乎没有任何法典:

template < class DERIVED >
class Foo
{
public:
    static int s_id()
    {
        return reinterpret_cast<int>(&s_id);
    }
};

www.un.org/Depts/DGACM/index_spanish.htm 在现代C++(03)中,假定您使用像“gcc”这样的最近汇编者,您可使用 字面。 获取至少可操作时间提供基本类型信息的类型“信息”的关键词——该词具有标准(然后是跨平台)特征

我从阴道上举出了一个例子,并增加了一个模板/历史检查,看来在固定版本中运行良好,但并不确定(即一个黑板,利用这样一种假设,即汇编者在阅读空间中将有一些名字......可能是错误的假设)。

如果你在你的案件中能够使用这种标识,那么在交叉产品识别方面,识别标识似乎要好得多。 它没有相互兼容,因为它给你的名称是标准规定的“执行”——正如评论所建议的。

完整的测试应用代码:

#include <iostream>
#include <typeinfo>  //for  typeid  to work

class Person 
{
public:
   // ... Person members ...
   virtual ~Person() {}
};

class Employee : public Person 
{
   // ... Employee members ...
};

template< typename DERIVED >
class Test
{
public:
    static int s_id()
    {
        // return id unique for DERIVED
        // NOT SURE IT WILL BE REALLY UNIQUE FOR EACH CLASS!!
        static const int id = reinterpret_cast<int>(typeid( DERIVED ).name());
        return id;
    }

    static const char* s_name()
    {
        // return id unique for DERIVED
        // ALWAYS VALID BUT STRING, NOT INT - BUT VALID AND CROSS-PLATFORM/CROSS-VERSION COMPATBLE
        // AS FAR AS YOU KEEP THE CLASS NAME
        return typeid( DERIVED ).name();
    }
};

int wmain () 
{
    Person person;
    Employee employee;
    Person *ptr = &employee;



    std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)
    std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
    std::cout << typeid(ptr).name() << std::endl;      // Person * (statically known at compile-time)
    std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time
                                                    // because it is the dereference of a pointer to a polymorphic class)

    Test<int> test;
    std::cout << typeid(test).name() << std::endl;    
    std::cout << test.s_id() << std::endl;    
    std::cout << test.s_id() << std::endl;    
    std::cout << test.s_id() << std::endl;    
    std::cout << test.s_name() << std::endl;    

    Test< Person > test_person;
    std::cout << test_person.s_name() << std::endl;    
    std::cout << test_person.s_id() << std::endl;    

    Test< Employee > test_employee;
    std::cout << test_employee.s_name() << std::endl;    
    std::cout << test_employee.s_id() << std::endl;    

    Test< float > test_float;
    std::cout << test_float.s_name() << std::endl;    
    std::cout << test_float.s_id() << std::endl;    


    std::cin.ignore();
    return 0;
}

产量:

class Person
class Employee
class Person *
class Employee
class Test<int>
3462688
3462688
3462688
int
class Person
3421584
class Employee
3462504
float
3462872

这至少是关于VC10Beta1和VC9的工作,应当就海湾合作委员会开展工作。 因此,为了使用打字(和有活力的播音),你必须允许在编辑上打字。 它应当违约。 在一些板块/组件(一对一些嵌入式硬件的思考)上,RTTI由于成本而没有被放弃,因此,在某些极端情况下,你不得不找到更好的解决办法。

在我以前的公司中,我们之所以这样做,是因为建立了一个宏观,将阶级名称作为参数,形成一个具有独特性(基于阶级名称)的当地静态,然后在返回静态成员的基类中确立一种虚拟功能。 这样一来,你就可以从物体等级的任何一种情况获得该身份证明,类似于ava物体的“Class()”方法,尽管更是原始。

我对迄今的答复感到不快,我为我找到了一种解决办法。 想法是用“Info”来计算一个字面。 每次在装货申请时都做过,因此没有超负荷运行。 这一解决办法还将使用共享图书馆作为名称,其名称和散射线一致。

这是我使用的法典。 这对我来说是巨大的。

#include <string>
#include <typeinfo>
#include <stdint.h>

//###########################################################################
// Hash
//###########################################################################
#if __SIZEOF_POINTER__==8
inline uint64_t hash(const char *data, uint64_t len) {
    uint64_t result = 14695981039346656037ul;
    for (uint64_t index = 0; index < len; ++index)
    {
        result ^= (uint64_t)data[index];
        result *= 1099511628211ul;
    }
    return result;
}
#else
inline uint32_t hash(const char *data, uint32_t len) {
    uint32_t result = 2166136261u;
    for (uint32_t index = 0; index < len; ++index)
    {
        result ^= (uint32_t)data[index];
        result *= 16777619u;
    }
    return result;
}
#endif
inline size_t hash(const std::string & str) { return hash(str.c_str(), str.length()); }

//###########################################################################
// TypeId
//###########################################################################
typedef size_t TypeId;

template<typename T>
static const std::string & typeName() {
    static const std::string tName( typeid(T).name() );
    return tName;
}
template<typename T>
static TypeId typeId() {
    static const TypeId tId = hash( typeName<T>() );
    return tId;
}
#include <stdint.h>
#include <stdio.h>

#define DEFINE_CLASS(class_name) 
    class class_name { 
    public: 
        virtual uint32_t getID() { return hash(#class_name); } 

// djb2 hashing algorithm
uint32_t hash(const char *str)
{
    unsigned long hash = 5381;
    int c;

    while ((c = *str++))
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;
}

DEFINE_CLASS(parentClass)

    parentClass() {};
    ~parentClass() {};
};

DEFINE_CLASS(derivedClass : public parentClass)

    derivedClass() : parentClass() {};
    ~derivedClass() {};
};

int main() {
    parentClass parent;
    derivedClass derived;
    printf("parent id: %x
derived id: %x
", parent.getID(), derived.getID());
}

何种身份识别? 你们是否指望得到原子增长? 如果扼杀是罚款,那么:

static string s_id()
{
   return typeid(Foo<DERIVED>).name();
}

如果它必须是隐蔽的,但并非自动增加,那么你就可以知道,对于128个轨道的星群来说,不可能发生碰撞(尽管可能比你需要多得多)。

The following snippet work in VS(2015) and Release Building:

template <typename T>
struct TypeId
{
  static size_t Get()
  {
    return reinterpret_cast<size_t>(&sDummy);
  }

private:
  static char sDummy;
};

template <typename T>
char TypeId<T>::sDummy; // don t care about value

还在海合会第7.3号(Ubuntu 1604)和LFL诉10.0.0号(Mac OS High Sierra)上进行了试验和测试。

如何运作:每个瞬时使用<代码>TypeId<>模板都有其自己的独特的大陪审团,有其独特的地址。 为了诚实,我不全心全意地确定,为什么功能-统计版本在释放时没有工作——我怀疑同志同道合和优化。

阅读器的演练:至少应当获得与原始类型相同的类型识别。

没有任何标准。 此外,我没有发现这种无ool的黑板。

最好的一号是:

template < class DERIVED, int sid >
class Foo
{
    public:    
      static int s_id()    
      {        
          return sid;
      }    
};

Foo<MyClass, 123456>   derivedObject;

你可以做以下工作:

#include <iostream>


template <int id = 5>
class blah
{
public:
    static const int cid = id; 
};

int main(int argc, char *argv[])
{
    std::cout << blah<>::cid << " " << blah<10>::cid << std::endl;

}

我不知道这是否是一个好主意。 The blah<> part is a bit unuitive. 也许你会更妥善地调换手法,或者你能够打造一个基类,给它一个与你的班子相提的模板。

Paul Houx 指出here,凡返回静态方法的地址,可能因编辑优化而无法工作。 但是,我们可以使用<代码>__FILE__和_LINE__ 宏观s+volaful等关键词进行工作。

最终解决办法将探讨这样的问题:

#define GET_TYPE_ID static size_t GetTypeId()   
{                                               
    volatile const char* file = __FILE__;       
    volatile uint32_t line = __LINE__;          
    return (size_t)&GetTypeId;                  
}

class ClassA
{
public:
    GET_TYPE_ID
};

class ClassB
{
public:
    GET_TYPE_ID
};




相关问题
热门标签