Уникальный идентификатор типа класса, который безопасен и содержит через границы библиотеки

Для применения на всех тегах привязки используйте

CSS

a:visited{
    color:blue;
}

Для применения только на некоторых тегах привязки используйте

CSS

.linkcolor a:visited{
    color:blue;
}

HTML

<span class="linkcolor"><a href="http://stackoverflow.com/" target="_blank">Go to Home</a></span>
12
задан xeon 28 May 2009 в 18:26
поделиться

6 ответов

Вот что я в итоге сделал. Если у вас есть отзывы (за, против), дайте мне знать.


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 статическим константой, поэтому ему нужно будет вычислять только один раз для каждого ВЫВОДА.

1
ответ дан 2 December 2019 в 06:09
поделиться

В современном C ++ (03 - при условии, что вы используете последний компилятор, такой как gcc), вы можете использовать ключевое слово typeid , чтобы получить объект type_info, который предоставляет базовую информацию о типах по крайней мере, во время выполнения - это стандартная (а затем и кроссплатформенная) функция .

Я взял пример из википедии и добавил проверку шаблона / наследования, похоже, он работает хорошо, но я не уверен в версии int (это взлом, использующий предположение, что компилятор будет иметь имена типов где-то в область памяти только для чтения ... это может быть неправильным предположением).

Строковый идентификатор кажется намного лучше для межплатформенной идентификации, если вы можете использовать его в своем случае. Он не совместим с кросс-компилятором, так как имя, которое он дает, "определяется реализацией". по стандарту - как предлагается в комментариях.

Полный код тестового приложения:

#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, должно работать на GCC. Кстати, чтобы использовать typeid (и dynamic_cast), вы должны разрешить информацию о типах времени выполнения в вашем компиляторе. По умолчанию он должен быть включен. На некоторых платформах / компиляторах (я думаю о некоторых встроенных аппаратных средствах) RTTI не включается, потому что это требует затрат, поэтому в некоторых крайних случаях вам придется найти лучшее решение.

8
ответ дан 2 December 2019 в 06:09
поделиться

В моей предыдущей компании мы сделал это, создав макрос, который примет имя класса в качестве параметра, создаст локальную статику с уникальным идентификатором (на основе имени класса), а затем создаст переопределение виртуальной функции, объявленной в базовом классе, которая вернула статический член. Таким образом, вы можете получить идентификатор во время выполнения из любого экземпляра иерархии объектов, аналогично методу getClass () в java-объекте, но гораздо более примитивно.

2
ответ дан 2 December 2019 в 06:09
поделиться

Нет ничего стандартизированного. Кроме того, я не нашел никакого взлома, который был бы надежным.

Лучшее, что я смог придумать:

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

Foo<MyClass, 123456>   derivedObject;
0
ответ дан 2 December 2019 в 06:09
поделиться

Какой идентификатор? Вы ищете атомарно увеличивающееся int? Если со строкой все в порядке, как насчет:

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

Если это должно быть int, но не увеличивающееся автоматически, вы можете хешировать это для 128-битного целого числа, которое вряд ли будет иметь коллизии (хотя, вероятно, большее число, чем вам нужно)

1
ответ дан 2 December 2019 в 06:09
поделиться

You может сделать следующее:

#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;

}

Я не знаю, хорошая ли это идея. Часть blah <> тоже немного неинтуитивна. Может быть, вам лучше назначить им идентификаторы вручную, или вы можете создать базовый тип, передав ему аргумент шаблона с идентификатором вашего класса.

0
ответ дан 2 December 2019 в 06:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: