какой смысл копипастить вопросы со стек офервлова, не читая ответы там ?
как вы смогли так долго продержаться в ИТ игнорируя возможности поисковика гугл ?
Здравствуйте, nen777w, Вы писали:
N>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? N>И есть ли возможность таки этот адрес получить?
В том-то и дело, что конструкторы — это не обычные функции, а специальные. Кострукторы не имеют имен, и используются только для инициализации объектов. Время жизни объекта начинается ПОСЛЕ выхода из конструктора. Другими словами, конструктор выполняется, когда время жизни объекта еще не началось и это принципиальное отличие — вызов конструктора для сконструированного объекта недопустим и невозможен (не путать с inplace конструированием, которое является инициализацией НОВОГО объекта с повторым использованием хранилища (storage)). В то же время указатели на функции-члены подразумевают использование с инициализированными объектами, что идет в разрез с требованиями, предъявляемыми к конструкторам.
15.1 Constructors 2 A constructor is used to initialize objects of its class type. Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the functional notation (8.2.3) will cause a constructor to be called to initialize an object. [ Note: For initialization of objects of class type see 15.6. —end note ]
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, nen777w, Вы писали:
N>Добрый час!
N>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция?
Потому что в C++ много чего сделано через жопу. И это в том числе.
N>И есть ли возможность таки этот адрес получить?
Нафига? Если сильно хочется сделайте функцию создающую экземпляр и используйте её адрес.
Здравствуйте, nen777w, Вы писали:
N>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? N>И есть ли возможность таки этот адрес получить?
Потому, что с этим адресом нельзя сделать ничего полезного.
Здравствуйте, nen777w, Вы писали:
N>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция?
Конструктор — это метод класса. Обычный метод класса для вызова требует иметь объект, для которого этот метод вызывается. Конструктор не нуждается в объекте для вызова, следовательно конструктор — не обычный метод класса.
N>И есть ли возможность таки этот адрес получить?
А вам зачем?
Здравствуйте, nen777w, Вы писали:
N>Добрый час!
N>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция?
Ну так и у функций класса получить адрес как бы не так просто получить.
Т.е. в определённых реализациях это будет возможно но в общем никак.
N>И есть ли возможность таки этот адрес получить?
Действительно стоит начать было тему с описанием зачем. https://rsdn.org/Info/howtoask.xml#E3CAC
N>>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? N>>И есть ли возможность таки этот адрес получить?
Pzz>Потому, что с этим адресом нельзя сделать ничего полезного.
А вот это не факт. Например мне понадобился этот адрес, и теперь нужно думать как это обойти.
N>>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? BFE>Конструктор — это метод класса. Обычный метод класса для вызова требует иметь объект, для которого этот метод вызывается. Конструктор не нуждается в объекте для вызова, следовательно конструктор — не обычный метод класса.
Да, но по сути это обычная функция (если рассматривать ее со стороны ассемблера).
N>>И есть ли возможность таки этот адрес получить? BFE>А вам зачем?
Если кратко, это связано с самописным протектором который я использую в своем приложении.
Вот другая моя тема с этим связанная: http://rsdn.org/forum/asm/7487846
Здравствуйте, nen777w, Вы писали:
N>Да, но по сути это обычная функция (если рассматривать ее со стороны ассемблера).
Вообще говоря такой гарантии нет. Простейщий вариант — это inline конструктор.
N>>>И есть ли возможность таки этот адрес получить? BFE>>А вам зачем? N>Если кратко, это связано с самописным протектором который я использую в своем приложении. N>Вот другая моя тема с этим связанная: http://rsdn.org/forum/asm/7487846
Вряд ли я с этим смогу помочь, могу только сказать, что конструктор класса можно сделать приватным, а создание с помощью static функции, адрес которой можно взять:
class A
{
private:
A(){}
public:
static A* CreateA() { return new A(); }
void Foo() {std::cout << "A::Foo()\n";}
};
int main()
{
A* (*pFn)() = &A::CreateA;
A* p = pFn();
p->Foo();
std::cout << "ok\n";
return 0;
}
Здравствуйте, B0FEE664, Вы писали:
BFE>Конструктор не нуждается в объекте для вызова
Если я правильно помню, то конструктор не выделяет память для объекта, указатель на область памяти, которую он должен инициализировать он получает извне.
Так что данное утверждение — ложно.
Здравствуйте, 0x7be, Вы писали:
BFE>>Конструктор не нуждается в объекте для вызова 0>Если я правильно помню, то конструктор не выделяет память для объекта, указатель на область памяти, которую он должен инициализировать он получает извне. 0>Так что данное утверждение — ложно.
Не надо путать объект с местом для его размещения — это не одно и тоже.
Здравствуйте, B0FEE664, Вы писали:
BFE>Не надо путать объект с местом для его размещения — это не одно и тоже.
А в чем существенная разница в контексте заданного вопроса?
Здравствуйте, 0x7be, Вы писали:
BFE>>Не надо путать объект с местом для его размещения — это не одно и тоже. 0>А в чем существенная разница в контексте заданного вопроса?
Зависит от того, что называть существенным. В С++ есть отдельный синтаксис для вызова конструктора с указанием места, где должен быть размещён объект. См. ответ kov_serg.
То, что синтаксис особый — это не просто так.
Допустим у нас есть возможность взять адрес конструктора, тогда вызов такого конструктора через указатель должен выглядеть как-то так:
class A
{
public:
A(){}
};
auto p = &A::A; // если не auto, то что?char buf[sizeof A]; // игнорируем проблему выравнивания
(buf->*p)(); // странно как-то, у char есть метод ?
(((void*)(buf))->*p)(); // у void есть метод?
(buf.*p)(); // как-то странно...
Таким образом, для вызова конструктора через указатель нужен отдельный синтаксис. Т.е. у нас получится ещё одно семейство указателей с ещё и специфическим синтаксисом вызова этих указателей. А весь выигрыш будет состоять только в том, что вместо new (buf) A; можно будет написать new (buf) p; например.
Хотя всё это мелочи. Главный вопрос: зачем в рамках самого языка может понадобиться иметь такие указатели? Вне языка, как у топикастера, это понятно, но стоит ли ради таких специфичных задач менять сам язык?
Здравствуйте, nen777w, Вы писали:
Pzz>>Потому, что с этим адресом нельзя сделать ничего полезного.
N>А вот это не факт. Например мне понадобился этот адрес, и теперь нужно думать как это обойти.
Здравствуйте, B0FEE664, Вы писали:
BFE>Таким образом, для вызова конструктора через указатель нужен отдельный синтаксис. Т.е. у нас получится ещё одно семейство указателей с ещё и специфическим синтаксисом вызова этих указателей. А весь выигрыш будет состоять только в том, что вместо new (buf) A; можно будет написать new (buf) p; например.
Не обязательно нужен новый синтаксис, это решаемые вопросы.
BFE>Хотя всё это мелочи. Главный вопрос: зачем в рамках самого языка может понадобиться иметь такие указатели? Вне языка, как у топикастера, это понятно, но стоит ли ради таких специфичных задач менять сам язык?
Это хороший вопрос. Скорее всего, топикстартеру тоже нужно не совсем то, что может ему дать ссылка на конструктор. Скорее всего он имеет в виду что-то типа виртуальной фабрики класса.
N>>>И есть ли возможность таки этот адрес получить? BFE>>А вам зачем?
N>Если кратко, это связано с самописным протектором который я использую в своем приложении.
Чет мне кажется, что если ты и получишь адрес конструктора, то не факт, что компилятор не заинлайнит где-то вызов конструктора. Т.е. если ты его перехватишь (типа как перехватывается вызов методов в HippoMocks), то не факт, что перехватятся все вызовы конструктора.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, nen777w, Вы писали:
N>>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? N>>И есть ли возможность таки этот адрес получить?
R>В том-то и дело, что конструкторы — это не обычные функции, а специальные. Кострукторы не имеют имен, и используются только для инициализации объектов. Время жизни объекта начинается ПОСЛЕ выхода из конструктора. Другими словами, конструктор выполняется, когда время жизни объекта еще не началось и это принципиальное отличие — вызов конструктора для сконструированного объекта недопустим и невозможен (не путать с inplace конструированием, которое является инициализацией НОВОГО объекта с повторым использованием хранилища (storage)). В то же время указатели на функции-члены подразумевают использование с инициализированными объектами, что идет в разрез с требованиями, предъявляемыми к конструкторам.
R>
R>15.1 Constructors
R>2 A constructor is used to initialize objects of its class type. Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the functional notation (8.2.3) will cause a constructor to be called to initialize an object. [ Note: For initialization of objects of class type see 15.6. —end note ]
На мой взгляд, в конструкторах не хватает одной важной возможности. А именно — перед инициализацией полей и вызова конструктора базового класса (это то, что идёт после двоеточия), очень нужно бывает выполнить какой-нибудь код. Вычислить различные величины, например. Чтобы потом их скормить в этой инициализации.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, nen777w, Вы писали:
N>>Добрый час!
N>>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? _>Потому что в C++ много чего сделано через жопу. И это в том числе.
N>>И есть ли возможность таки этот адрес получить? _>Нафига? Если сильно хочется сделайте функцию создающую экземпляр и используйте её адрес. _>
Дело в том, что в этой новой функции надо будет указать параметры — такие же, как у конструктора. Ты устанешь всё это прописывать и поддерживать.
А ещё — помню (смутно правда) стояла задача написать шаблон, чтобы для произвольного типа был некий класс, содержащий объект этого типа, и указатель. Ну чтобы связный список организовать. Я так и не додумался, как можно обеспечить передачу параметров в конструктор этого объекта. По-моему так дело обстояло.
J>Дело в том, что в этой новой функции надо будет указать параметры — такие же, как у конструктора. Ты устанешь всё это прописывать и поддерживать. J>А ещё — помню (смутно правда) стояла задача написать шаблон, чтобы для произвольного типа был некий класс, содержащий объект этого типа, и указатель. Ну чтобы связный список организовать. Я так и не додумался, как можно обеспечить передачу параметров в конструктор этого объекта. По-моему так дело обстояло.
Слушайте, что за глюк на сайте? Я сейчас добавил свои эти два сообщения. Открыты 2 вкладки браузера. В одной, я зашёл под своим аккаунтом, и в этом треде эти сообщения вижу. А в другой, открытой ранее, я не зашёл, и сообщений нет. Хотя и обновил страницу.
Здравствуйте, jamesq, Вы писали:
J>На мой взгляд, в конструкторах не хватает одной важной возможности. А именно — перед инициализацией полей и вызова конструктора базового класса (это то, что идёт после двоеточия), очень нужно бывает выполнить какой-нибудь код. Вычислить различные величины, например. Чтобы потом их скормить в этой инициализации.
Сейчас это легко делается при помощи делегирующих конструкторов:
class A
{
public:
A(int a, int b) : A(a, b, double(a - b)/(a + b)) {}
private:
A(int a, int b, double x) : a(a), b(b), c(x - 10), d(x * 20) {}
int a;
int b;
double c;
double d;
};
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, jamesq, Вы писали:
J>Дело в том, что в этой новой функции надо будет указать параметры — такие же, как у конструктора. Ты устанешь всё это прописывать и поддерживать. J>А ещё — помню (смутно правда) стояла задача написать шаблон, чтобы для произвольного типа был некий класс, содержащий объект этого типа, и указатель. Ну чтобы связный список организовать. Я так и не додумался, как можно обеспечить передачу параметров в конструктор этого объекта. По-моему так дело обстояло.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, jamesq, Вы писали:
J>>Дело в том, что в этой новой функции надо будет указать параметры — такие же, как у конструктора. Ты устанешь всё это прописывать и поддерживать. J>>А ещё — помню (смутно правда) стояла задача написать шаблон, чтобы для произвольного типа был некий класс, содержащий объект этого типа, и указатель. Ну чтобы связный список организовать. Я так и не додумался, как можно обеспечить передачу параметров в конструктор этого объекта. По-моему так дело обстояло.
_>
Ох уж этот новый C++ ...
Клёво конечно, но сколько ж можно всего изучать! У меня уже давно голова пухнет. Все кому не лень, налево и направо придумывают всякое, а ты давай учи!
J>Ох уж этот новый C++ ... J>Клёво конечно, но сколько ж можно всего изучать! У меня уже давно голова пухнет. Все кому не лень, налево и направо придумывают всякое, а ты давай учи!
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, jamesq, Вы писали:
J>>Ох уж этот новый C++ ... J>>Клёво конечно, но сколько ж можно всего изучать! У меня уже давно голова пухнет. Все кому не лень, налево и направо придумывают всякое, а ты давай учи!
_NN>Новы C++ вышел 8 лет назад если что
Я знаю. Я сейчас другими вещами занимаюсь, просто. Не C++
M>Чет мне кажется, что если ты и получишь адрес конструктора, то не факт, что компилятор не заинлайнит где-то вызов конструктора. Т.е. если ты его перехватишь (типа как перехватывается вызов методов в HippoMocks), то не факт, что перехватятся все вызовы конструктора.
Да есть такое, но этим можно управлять, например отключив оптимизацию прагмами.
Но в целом идея понятна. Единственное что попробую улучшить это написать дополнительную функцию для поиска call <адрес конструктора> в этой get_ctor_addr().
Здравствуйте, Pzz, Вы писали:
N>>По каким соображением в С++ запретили брать адрес конструктора, если по сути он есть обычная функция? N>>И есть ли возможность таки этот адрес получить?
Pzz>Потому, что с этим адресом нельзя сделать ничего полезного.
Ну да, конечно. Аллоцировать память через operator new(sizeof(Object)) и вызвать что ли нельзя? Вот указателя нет на конструктор, потому и нельзя. Но можно унаследоваться от класса, сделать функцию с тем же прототипом и запросто вызвать! Но вопрос, конечно, откуда взять адрес самого конструктора. Я делаю так:
1) в конструктор кладётся конструкция наподобии такой:
2) через __start_symbols и __stop_symbols можно перечислять экземпляры SymbolInstance, которые имеют функцию, которая берёт адрес &&__thunk и через dladdr(3) находит и замангленное имя конструктора, и его настоящий адрес.
3) при линковке нужен ключик -Wl,-E или что-то похожее, чтоб конструкторы попали в динамическую таблицу символов (иначе dladdr не заработает).
J>На мой взгляд, в конструкторах не хватает одной важной возможности. А именно — перед инициализацией полей и вызова конструктора базового класса (это то, что идёт после двоеточия), очень нужно бывает выполнить какой-нибудь код. Вычислить различные величины, например. Чтобы потом их скормить в этой инициализации.
Ну так в круглых скобочках в выражении BaseClass(...) можно записать любые вычисляющие выражения. Вызовы функций (для C++03) или вписать лямбду (для C++11).
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, 0x7be, Вы писали:
BFE>>>Не надо путать объект с местом для его размещения — это не одно и тоже. 0>>А в чем существенная разница в контексте заданного вопроса?
BFE>Зависит от того, что называть существенным. В С++ есть отдельный синтаксис для вызова конструктора с указанием места, где должен быть размещён объект. См. ответ kov_serg.
Можно с этого момента поподробней? Всегда считал, что конструктор это такая же функция, как и любая функция член класса...
Отдельный синтаксис (placement new?) к самому конструктору никак не относится, в конструктор тупо передаётся this так же как и в другие функции-члены.
BFE>Таким образом, для вызова конструктора через указатель нужен отдельный синтаксис.
Чем не устраивает синтаксис применяемый для других функций-членов класса?
BFE>Хотя всё это мелочи. Главный вопрос: зачем в рамках самого языка может понадобиться иметь такие указатели?
Проксировать вызовы внешних (из динамически загружаемой библиотеки) функций, например. Получается если конструктор в динамической библиотеке, то его не вызвать через dlsym(3), но вызвать если слинковать с библиотекой при компиляции. Где логика?
Здравствуйте, kov_serg, Вы писали:
J>>Дело в том, что в этой новой функции надо будет указать параметры — такие же, как у конструктора. Ты устанешь всё это прописывать и поддерживать. J>>А ещё — помню (смутно правда) стояла задача написать шаблон, чтобы для произвольного типа был некий класс, содержащий объект этого типа, и указатель. Ну чтобы связный список организовать. Я так и не додумался, как можно обеспечить передачу параметров в конструктор этого объекта. По-моему так дело обстояло.
_>
Функция конструктора всё равно должна быть непосредственно доступна в link time.
Не вариант для слуачая, когда конструктор находится в .so/.dll не доступной в момент линковки.
Здравствуйте, fk0, Вы писали:
fk0>Не вариант для слуачая, когда конструктор находится в .so/.dll не доступной в момент линковки.
Если конструктор находится в динамической библиотеке — вы сам себе злобный буратино. Только C апи, на крайняк COM.
Если вы экспортируете C++ апи наружу — значит "что-то пошло не так".
Здравствуйте, Pzz, Вы писали:
fk0>> Ну да, конечно. Аллоцировать память через operator new(sizeof(Object)) и вызвать что ли нельзя? Pzz>Для этого есть специальный синтаксис, placement new называется.
При использовании placement new символ конструктора адресуется компилятором напрямую. А хочется-то через указатель, т.е. не используя напрямую символ конструктора.
Здравствуйте, kov_serg, Вы писали:
fk0>>Не вариант для слуачая, когда конструктор находится в .so/.dll не доступной в момент линковки. _>Если конструктор находится в динамической библиотеке — вы сам себе злобный буратино. Только C апи, на крайняк COM. _>Если вы экспортируете C++ апи наружу — значит "что-то пошло не так".
Не вижу принципиальных проблем, если shared object будет линковаться в момент сборки.
Возможно есть какие-то corner cases неочевидные, но сходу не незвал бы.
Идиотические случаи (всё связанное с микрософтом и использование разных компиляторов) не рассматриваем.
Здравствуйте, fk0, Вы писали:
fk0> При использовании placement new символ конструктора адресуется компилятором напрямую. А хочется-то через указатель, т.е. не используя напрямую символ конструктора.
Я вот только не могу понять, к чему оно тебе такое хочется.