2009-12-13 40 views

Trả lời

58

Không before C++11.

Trích xuất chức năng chung thành một hàm riêng biệt thay thế. Tôi thường đặt tên cho chức năng này là xây dựng().

Cuộc gọi thứ hai "được gọi là" sẽ biên dịch, nhưng có ý nghĩa khác trong C++: nó sẽ xây dựng một đối tượng mới, tạm thời, sau đó sẽ bị xóa ngay vào cuối câu lệnh. Vì vậy, không.

Một trình phá hủy, tuy nhiên, có thể được gọi mà không có sự cố.

+2

1 - và 'construct()' là một tên tốt. – peterchen

+5

+1 - và bạn nên thêm rằng nó sẽ có thể gọi các nhà thầu từ các nhà xây dựng trong cùng một lớp trong phiên bản C++ tiếp theo (C++ 0x). Xem http://www2.research.att.com/~bs/C++0xFAQ.html#delegating-ctor – Klaim

+0

Bạn có thể đưa ra ví dụ về hàm construct() không? Tôi biết nó khá đơn giản nhưng tôi nghĩ mọi người sẽ thấy nó hữu ích. – MattClimbs

16

Không phải trước C++0x, không.

NHƯNG, chỉ ra quan tâm học tập Tôi đã tìm ra một cách thực sự khủng khiếp * để làm điều đó bằng cách sử dụng toán tử vị trí "mới" (chăm sóc một ai đó chỉ ra cách cầm tay này là gì?)

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

* Không, tôi không viết mã này trong mã sản xuất.

+1

Tôi nghĩ rằng nó khá di động; vị trí mới nằm trong tiêu chuẩn ISO C++. "Các ứng dụng khác, tuy nhiên, bao gồm gọi trực tiếp một nhà xây dựng, một thứ mà ngôn ngữ C++ không cho phép." Từ wikipedia: http://en.wikipedia.org/wiki/Placement_syntax – haavee

+4

Điều gì xảy ra nếu A xuất phát từ một lớp B? B của constructor sẽ được gọi, và sau đó A, mà sau đó sẽ gọi mới A '(khác A constructor), và ghi đè lên tất cả mọi thứ đã được thực hiện bởi B, và sau đó gọi B một lần nữa, sau đó A'. Kết luận: nếu B thực hiện điều gì đó có ý nghĩa (nghĩa là phân bổ tài nguyên), điều này sẽ phá vỡ mã (tức là kích hoạt rò rỉ tài nguyên). – paercebal

+0

@paercebal có, điều này cũng sẽ không hoạt động nếu A là lớp trừu tượng. –

5

Câu trả lời thực tế là "có", nhưng như những người khác đã đề xuất, nó không làm những gì bạn muốn. Tất nhiên, bạn có thể sử dụng hàm tạo của một lớp cơ sở, hoặc ngầm hoặc rõ ràng:

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

Không trực tiếp. Có một số cách để giải quyết vấn đề này.

Từ danh sách khởi tạo của hàm tạo lớp, bạn có thể gọi hàm tạo trên bất kỳ lớp cơ sở nào và trên tất cả các biến thành viên.

Vì vậy, bạn thường có thể cấu trúc lại lớp của mình và chia nhỏ thành nhiều lớp nhỏ hơn để giải quyết vấn đề. Mã thường được thực hiện có thể được đặt trong một đối tượng thành viên hoặc có thể là một lớp cơ sở. Sau đó, mỗi nhà xây dựng của lớp chính chỉ phải quyết định construcotr nào sẽ sử dụng để khởi tạo thành viên đó.

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

Đây là câu hỏi cũ; Tuy nhiên,

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

có thể

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

Tôi nghĩ rằng việc gán '* this = A();' nó sẽ sử dụng hàm tạo bản sao mặc định (nếu bạn chưa định nghĩa một) mà có thể không phải là những gì bạn muốn? – austinmarton

Các vấn đề liên quan