2009-12-13 3 views

ответ

58

Не before C++11.

Извлечь общую функциональность в отдельную функцию. Обычно я называю эту функцию construct().

«Так называемый» второй вызов будет скомпилирован, но имеет другое значение в C++: он создаст новый объект, временный, который затем будет немедленно удален в конце инструкции. Итак, нет.

Деструктор, однако, можно назвать без проблем.

+2

+1 - и 'construct()' - хорошее имя. – peterchen

+5

+1 - и вы должны добавить, что можно будет вызвать конструкторы из конструкторов в том же классе в следующей версии C++ (C++ 0x). См. Http://www2.research.att.com/~bs/C++0xFAQ.html#delegating-ctor – Klaim

+0

Можете ли вы привести пример функции construct()? Я знаю, что это довольно просто, но я думаю, что люди сочтут это полезным. – MattClimbs

16

Не раньше C++0x, no.

НО, только из академического интереса я придумал действительно ужасным способом *, чтобы сделать это с помощью оператора размещения «новый» (кто-то забота, чтобы указать, как портативный это?)

#include <new> 
#include <iostream> 

class A 
{ 
public: 
    A(int i, int j) 
     : i_(i), j_(j) { } 

    A(int i) 
    { new (this) A(i, 13); } 

    int i_,j_; 
}; 

int 
main() { 
    A a1(10,11), a2(10); 
    std::cout 
     << a1.i_ << ", " 
     << a1.j_ << std::endl 
     << a2.i_ << ", " 
     << a2.j_ << std::endl; 
    return 0; 
} 

* Ад нет, я не пишу это в производственном коде.

+1

Я думаю, что это довольно портативно; place-new находится в стандарте ISO C++. «Другие использования, однако, включают вызов конструктора напрямую, то, что не разрешает другой язык C++». Из Википедии: http://ru.wikipedia.org/wiki/Placement_syntax – haavee

+4

Что произойдет, если A происходит от класса B? Будет вызываться конструктор B, а затем A, который затем вызовет новый A '(другой конструктор A) и перезапишет все, что уже сделано B, а затем снова вызовет B, затем A'. Вывод: если B делает что-то значимое (т. Е. Выделяет ресурс), это нарушит код (т. Е. Спровоцирует утечку ресурса). – paercebal

+0

@paercebal да, это также не сработает, если A - абстрактный класс. –

5

Ответ на самом деле «да», но, как предложили другие, он не делает то, что вы хотите. Вы можете, конечно, использовать конструктор базового класса неявно или явно:

struct B { 
    B() {} 
    B(int x) {} 
}; 

struct A : public B { 
    A() {} // calls B() implicitly 
    A(int a, int b) : B(b) {} // calls B(int) explicitly 
}; 
3

Не напрямую. Есть несколько способов обойти это.

Из списка инициализаторов конструктора вашего класса вы можете вызвать конструктор для любого базового класса и всех переменных-членов.

Таким образом, вы можете реорганизовать свой класс и разделить его на несколько меньших, чтобы решить эту проблему. Обычно исполняемый код может быть помещен в объект-член или, возможно, в базовый класс. Затем каждый из конструкторов основного класса должен решить, какой конструктор использовать для инициализации этого элемента.

class B { 
    B() { } 
    B(int b) { DoSomething(); } 
} 
class A{ 
    A(int a = 5) : b(a) { } // call B's constructor which does something 
    A() : b() {} // call B's constructor which does nothing 

    B b; 
}; 
1

Это старый вопрос; Однако

class A{ 
    A(int a = 5){ 
    DoSomething(); 
    A(); 
    } 
    A(){...} 
} 

может быть

class A{ 
    A(int a = 5){ 
    *this = A(); 
    DoSomething(); 
    } 
    A(){...} 
} 
+1

Я думаю, что назначение '* this = A();' будет использовать конструктор копии по умолчанию (если вы его не определили), который может быть не таким, каким вы хотите? – austinmarton

Смежные вопросы