C++ вызов конструктора из конструктора
вроде как нельзяРаботает, т.к. operator new можно перегружать и существует его стандартная перегрузка void * operator new (size_t bytes, void * mem которая и используется в этом примере. Это называется placement new и используется для написания собственных распределителей памяти.
однако в гугле нашел решение
токо терь не пойму как оно работает
закомментированная строчка будет работать в вижуалсстудииНу, это проблемы вижуалсстудии, если она на эту строчку даже предупреждения не выдает.
но она вроде как противоречит стандарту
Вообще, вызывать конструктор из конструктора это очень плохая идея, т.к. черевато ошибками, например:
#include <iostream>
struct B {
B {
std::cout << "B::B" << std::endl;
p = new char[10];
}
~B {
std::cout << "B::~B" << std::endl;
delete p;
}
char * p;
};
struct D : public B {
D(int) {
std::cout << "D::D(int)" << std::endl;
}
D {
std::cout << "D::D" << std::endl;
new (this)D(1);
}
~D {
std::cout << "D::~D" << std::endl;
}
};
int main {
D d;
return 0;
}
В результате имеем утечку памяти:
B::B
D::D
B::B
D::D(int)
D::~D
B:~B
Могут возникать и более хитрые проблемы, например, если бы в твоем примере выше встретилось бы
class A;
void * operator new(size_t size, A * mem)
{
return std::memset(mem, 0, size);
}
то результат его работы был бы другим.
Так что вместо вызова одного конструктора из другого лучше написать функцию инициализации и звать ее изо всех конструкторов.
даже если бы оба варианта работали по стандарту, то тем не менее они грязные. можно сделать метод инициализации и его вызвать из обоих конструкторов (если требуется избавиться от копи-паста)
</offtopic>
не нашел в коде места, где берется адрес конструктора
Вкратце - чувак, тебе это не нужно. Подожди С++0x, там это можно будет легально делать.
баян значится
блин ну чё за глупости, неужели не понятно, что ты так дважды поля b и c проинициализируешь. а если их тип чуть сложнее чем int, память например аллоцируется при инициализации...
а что насчёт возможности Java, C# вызова другого конструктора?
а что насчет сборки мусора в Java, C#?
надо только, как в первом примере, не делать инициализацию вне них.
а что насчёт возможности Java, C# вызова другого конструктора?в C# вызывать можно, но только в самом начале через специальный синтаксис
class A
{
public A(int a){this.b=a;}
public A(int a, int c):this(a){this.c = c;}
int b;
int c;
}
надо только, как в первом примере, не делать инициализацию вне них.и чем это поможет примеру ?
в C# вызывать можно, но только в самом начале через специальный синтаксися к тому, что компилятор сам следит за выполнением конструкторов и инициализацию аккуратно обходит, потому проблем не возникает.
struct Int {
int * x;
Int {x = new int;}
~Int { delete x; }
}
class C {
Int x;
C (int z)
{
*(x.x) = z;
}
C
{
new (this) C(0);
}
}
C c; //new int случается дважды!
и чем это поможет примеру ?ну да, этот пример показывает, что лучше применять это не в конструкторах, о которых компилятор слишком много знает, а в каких-нить init'ах, вызываемых сразу из конструкторов.
new int случается дважды!Ты инициализацию оставил вне конструктора
Если третье, то это тупо неверно. В том же сишарпе инициализация довольно тривиально отделена от конструкторов, поэтому происходит один раз. Более того, там ещё всё веселей, порядок такой: вначале выполняются инициализаторы от most derived class к least derived (то есть к System.Object, если бы они у него были) потом выполняются конструкторы в обратном порядке (то есть вначале least derived). Сделано это затем, чтобы даже если ты вызываешь в конструкторе виртуальную функцию, она всё равно увидит инициализированные поля своего реального класса, инициализированные только инициализаторами, а не конструктором, конечно, но и то хлеб.
Я к тому, что в результате необходимость как-то дать возможность писать вместо "public MyClass(bla bla) base(bla) {}" "public MyClass(bla bla) this(bla) {}" в общем-то уже не пугает, под Кандагаром было круче.
под Кандагаром было кручегде-где-где?
Оставить комментарий
pitrik2
вроде как нельзяоднако в гугле нашел решение
токо терь не пойму как оно работает
закомментированная строчка будет работать в вижуалсстудии
но она вроде как противоречит стандарту