Вы можете попробовать использовать Reflection
Type type = typeof(Employees);
PropertyInfo pi = this.GetType().GetProperty();
pi.SetField(this, value);
Вот ссылка MSDN: https://msdn.microsoft.com/en-us/library/ms173183.aspx
На самом деле существует перегрузка & lt; оператор, который выглядит примерно так:
ostream & operator <<( ostream &, const void * );
, который делает то, что вы ожидаете, - выводит в шестнадцатеричном формате. Не может быть такой стандартной перегрузки библиотек для указателей на функции, поскольку они представляют собой бесконечное количество типов. Таким образом, указатель преобразуется в другой тип, который в этом случае выглядит как bool - я не могу заранее запомнить правила для этого.
Изменить: в стандарте C ++ указано:
4.12 Логические преобразования
1 Значение арифметики, перечисления, указателя или указателя на тип члена может быть преобразовано в rvalue типа bool.
blockquote>Это единственное преобразование, указанное для указателей функций.
В C ++ 11 можно было изменить это поведение, указав переменную перегрузку шаблона operator<<
(независимо от того, является ли это рекомендуемым или нет, это другая тема):
#include<iostream>
namespace function_display{
template<class Ret, class... Args>
std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ){ // star * is optional
return os << "funptr " << (void*)p;
}
}
// example code:
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main(){
using namespace function_display;
// ampersands & are optional
std::cout << "1. " << &fun_void_void << std::endl; // prints "1. funptr 0x40cb58"
std::cout << "2. " << &fun_void_double << std::endl; // prints "2. funptr 0x40cb5e"
std::cout << "3. " << &fun_double_double << std::endl; // prints "3. funptr 0x40cb69"
}
const
, volatile
или const volatile
и может или может не иметь заднего многоточия.
– Brian
25 March 2015 в 21:37
double(const *ptr)(double) = &fun_double_double;
? (не стесняйтесь редактировать ответ, чтобы уточнить).
– alfC
25 March 2015 в 21:44
const
в эту позицию. Вы хотите поставить его перед ptr
, если вы хотите, чтобы постоянный указатель работал. Во всяком случае, этот случай уже покрыт вашим ответом, но я имею в виду что-то вроде double (T::*ptr)(double) const
.
– Brian
25 March 2015 в 21:55
const
(на самом деле const
или нет, это та же самая функция, const
избыточно). Да, функция указатель-член не была покрыта. Я понял, что это не вопрос. Но я добавил его к ответу сейчас.
– alfC
26 March 2015 в 00:50
template<class Ret, class T, class... Args> std::ostream& operator <<(std::ostream& os, Ret(T::* const p)(Args...) const){ // first const ins optional return os << "memfunptr const " << typeid(T).name() <<"::"<< reinterpret_cast<size_t const*>(&p); }
, но в основном все различные функции-члены печатают одинаковый номер.
– alfC
26 March 2015 в 01:00
Что касается вашего редактирования, вы можете распечатать содержимое чего-либо, обратившись к нему с помощью указателя unsigned char
. Пример для указателей на функции-члены:
#include <iostream>
#include <iomanip>
struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };
int main()
{
void (foo3::*p)() = &foo::bar;
unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);
for (; first != last; ++first)
{
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (int)*first << ' ';
}
std::cout << std::endl;
}
Указатели каста на (void*)
для печати их на cout
- это правильная вещь (TM), чтобы делать на C ++, если вы хотите увидеть их значения.
unsigned long
, unsigned long long
также может использоваться.
– curiousguy
21 October 2011 в 13:42
Вы можете думать, что указатель функции является адресом первой инструкции в машинный код этой функции. Любой указатель можно рассматривать как bool
: 0 - false, а все остальное - true. Как вы заметили, при нажатии на void *
и заданной в качестве аргумента для оператора вставки потока (<<
), адрес печатается. (Показать строго, приведение указателя к функции в void *
не определено.)
Без трансляции история немного сложна. Для сопоставления перегруженных функций («разрешение перегрузки») компилятор C ++ собирает набор функций-кандидатов, и из этих кандидатов выбирает «наилучшую жизнеспособную», используя при необходимости неявные преобразования. Морщинка - это правила сопоставления, которые образуют частичный порядок, поэтому множественные наиболее эффективные совпадения вызывают ошибку двусмысленности.
В порядке предпочтения стандартные преобразования (и, конечно, также конверсии, определяемые пользователем и многоточие, не подробные) являются
int
to float
) Последняя категория включает в себя логические преобразования, и любой тип указателя может быть преобразован в bool
: 0 (или NULL
]) - false
, а все остальное - true
. Последний отображается как 1
, когда передается оператору вставки потока.
Вместо этого вместо 0
измените свою инициализацию на
pf = 0;
. Помните, что инициализация указателя с нулевое константное выражение дает нулевой указатель.
bool
.
– curiousguy
26 October 2011 в 01:14
Что касается вашего конкретного вопроса,
, как мы можем наблюдать содержимое указателей на функцию-член?
blockquote>Ответ заключается, кроме преобразования их в bool, чтобы выразить, что он указывает на что-то или нет, вы не можете указывать функции-наблюдателя. По крайней мере, не соответствующим образом. Причина в том, что стандарт явно запрещает это:
4.12 примечание 57:
57) Правило для преобразования указателей на членов (от указателя к члену базы до указателя члену производного) представляется инвертированным по сравнению с правилом для указателей на объекты (от указателя к производному до указателя на базу) (4.10, раздел 10). Эта инверсия необходима для обеспечения безопасности типа. Обратите внимание, что указатель на элемент не является указателем на объект или указателем на функцию, а правила для преобразования таких указателей не применяются к указателям на члены. В частности, указатель на член не может быть преобразован в void *.
blockquote>Например, вот пример кода:
#include <cstdlib> #include <vector> #include <algorithm> #include <string> #include <iostream> using namespace std; class Gizmo { public: void DoTheThing() { return; }; private: int foo_; }; int main() { void(Gizmo::*fn)(void) = &Gizmo::DoTheThing; Gizmo g; (g.*fn)(); // once you have the function pointer, you can call the function this way bool b = fn; // void* v = (void*)fn; // standard explicitly disallows this conversion cout << hex << fn; return 0; }
Отмечу, что мой отладчик ( MSVC9) может рассказать мне фактический физический адрес функции-члена во время выполнения, поэтому я знаю, что должен быть какой-то способ получить этот адрес. Но я уверен, что он несоответствует, не переносится и, вероятно, включает машинный код. Если бы я пошел по этой дороге, я бы начал с адреса указателя функции (например,
&fn
), отбрасывая это на пустоту * и оттуда. Это также потребует, чтобы вы знали размер указателей (разные на разных платформах).Но я бы спросил, до тех пор, пока вы можете преобразовать указатель функции-члена в bool и оценить существование указателя, почему в реальном коде вам нужен адрес?
Предположительно, ответ на последний вопрос «так что я могу определить, указывает ли один указатель на функцию на ту же функцию, что и на другой». Справедливо. Вы можете сравнить указатели функций на равенство:
#include <cstdlib> #include <vector> #include <algorithm> #include <string> #include <iostream> using namespace std; class Gizmo { public: void DoTheThing() { return; }; **void DoTheOtherThing() { return; };** private: int foo_; }; int main() { void(Gizmo::*fn)(void) = &Gizmo::DoTheThing; Gizmo g; (g.*fn)(); // once you have the function pointer, you can call the function this way bool b = fn; // void* v = (void*)fn; // standard explicitly disallows this conversion cout << hex << fn; **void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing; bool same = fnOther == fn; bool sameIsSame = fn == fn;** return 0; }
&Type::member
, и используются одинаково, используя .*
или ->*
.
– Ben Voigt
14 June 2018 в 15:43
bool
. Примечательно, что вы должны выполнитьreinterpret_cast
, чтобы преобразоватьint (*)()
вvoid *
. – avakar 14 January 2010 в 15:40void *
является единственным преобразованием i>, но есть еще одна вещь, о которой нужно помнить: манипуляторы - это функции, адреса которых вы передаете в поток. Вместо преобразования их поток вызывает i> их; если вы передадите указатель на функцию с сигнатурой, подобной манипулятору, поток будет обрабатывать ее как манипулятор и вызывать функцию вместо попытки конвертировать свой адрес вообще. – Jerry Coffin 14 January 2010 в 16:22