2009-10-18 77 views
14

Chúng ta có phải xác định rõ ràng một hàm tạo mặc định khi chúng ta định nghĩa một hàm tạo bản sao cho một lớp không ?? Vui lòng đưa ra lý do.Sao chép Constructor và hàm tạo mặc định

ví dụ:

class A 
{ 
    int i; 

    public: 
      A(A& a) 
      { 
       i = a.i; //Ok this is corrected.... 
      } 

      A() { } //Is this required if we write the above copy constructor?? 
};  

Ngoài ra, nếu chúng ta định nghĩa bất kỳ constructor tham số khác cho một lớp khác với constructor sao chép, sao chúng ta cũng phải xác định các nhà xây dựng mặc định ?? Hãy xem xét mã ở trên mà không có hàm tạo bản sao và thay thế nó bằng

A(int z) 
{ 
    z.i = 10; 
} 

Alrite .... Sau khi xem câu trả lời tôi đã viết chương trình sau đây.

#include <iostream> 

using namespace std; 

class X 
{ 
    int i; 

    public: 
      //X(); 
      X(int ii); 
      void print(); 
}; 

//X::X() { } 

X::X(int ii) 
{ 
    i = ii; 
} 


void X::print() 
{ 
    cout<<"i = "<<i<<endl; 
} 

int main(void) 
{ 
    X x(10); 
    //X x1; 
    x.print(); 
    //x1.print(); 
} 

ANd chương trình này có vẻ hoạt động tốt mà không có hàm tạo mặc định. Xin giải thích tại sao lại là trường hợp này ?? Tôi thực sự bối rối với khái niệm này .....

+2

Tôi đang bối rối. Mặc dù câu trả lời dưới đây là chính xác, nhưng đó không phải là một hàm tạo bản sao. Bạn đang sao chép 'i', chính xác là ở đâu? Bạn đang sửa đổi phía bên tay phải, thường là điều sai trái. Bạn nên làm 'A (const A & rhs): i (rhs.i) {}', đó là sao chép phần bên phải 'i' vào trường hợp này của 'i'. Lưu ý các tham số được truyền theo hằng số, bởi vì khi bạn nói một cái gì đó như x = 3, 3 không nên thay đổi. Ngoài ra, thông thường các loại số được chuyển theo giá trị, không phải tham chiếu, bởi vì tham chiếu có thể chậm hơn đối với các loại dữ liệu nhỏ. – GManNickG

+0

Wow .... Cảm ơn bạn đã bình luận ... nó xóa bỏ sự nhầm lẫn về phần ": i (rhs.i)" của nhà xây dựng đã gây nhầm lẫn cho tôi kể từ khi tôi bắt đầu nghiên cứu các nhà thầu sáng nay .... –

+1

chương trình mới nhất không sử dụng hàm tạo mặc định ở bất kỳ đâu. Vì lý do này, bạn không cần phải xác định nó. Đó là tất cả để có nó. – AnT

Trả lời

33

Có. Khi bạn khai báo rõ ràng hoàn toàn bất kỳ một hàm tạo nào cho một lớp, trình biên dịch sẽ ngừng cung cấp hàm tạo ngầm mặc định. Nếu bạn vẫn cần hàm dựng mặc định, bạn phải tự khai báo và định nghĩa nó một cách rõ ràng.

P.S. Có thể viết một hàm tạo bản sao (hoặc hàm tạo chuyển đổi hoặc bất kỳ hàm tạo khác) nào cũng là một hàm dựng mặc định. Nếu constructor mới của bạn rơi vào trường hợp đó, không cần phải cung cấp một constructor thêm mặc định nữa :)

Ví dụ:

// Just a sketch of one possible technique  
struct S { 
    S(const S&); 
    S(int) {} 
}; 

S dummy(0); 

S::S(const S& = dummy) { 
} 

Trong ví dụ trên các nhà xây dựng bản sao là cùng lúc các nhà xây dựng mặc định .

+0

"Có thể viết một hàm tạo bản sao cũng là hàm tạo mặc định." Làm sao? – dalle

+0

Bằng cách thêm một đối số mặc định vào một construtor sao chép, ví dụ. Xem ví dụ tôi đã thêm vào phản hồi của tôi. – AnT

+0

Bạn có thể làm rõ câu hỏi đã chỉnh sửa của tôi không? Mã hoạt động tốt mà không cần định nghĩa hàm khởi tạo mặc định. –

3

Bạn không cần phải xác định cả hai. Tuy nhiên, khi bạn định nghĩa bất kỳ hàm tạo nào cho một lớp, tất cả các hàm khởi tạo mặc định sẽ không có sẵn. Vì vậy, nếu bạn muốn cả hai bản sao-xây dựng và xây dựng mà không cần sao chép, bạn cần phải xác định một mặc định (tức là rõ ràng) mặc định (tức là không có tham số) constructor quá.

Nếu bạn xác định hàm tạo bản sao, bạn cũng thường ghi đè toán tử gán.

+0

Bạn đang bối rối vấn đề bằng cách nạp quá "từ" mặc định. Không chỉ vậy nhưng ý nghĩa quá tải của bạn mặc định đã được giải thích với từ "rõ ràng" đó là một từ khóa dành riêng để sử dụng với các nhà xây dựng! Bạn có thể sử dụng tổng hợp thay vào đó (với z nếu bạn thích). :) – Troubadour

+0

Quá tải của từ "mặc định" là cố ý - nó chỉ buồn mà bạn không có ý nghĩa của wordplay. Đối với từ "rõ ràng" - sự tồn tại của ý nghĩa chuyên ngành trong ngôn ngữ C++ không làm mất hiệu lực ý nghĩa từ trước trong ngôn ngữ tiếng Anh. Và đối với "tổng hợp" - tôi nghĩ mục tiêu đã được hiểu? – Steve314

1

Như AndreyT đã nói, nếu bạn khai báo rõ ràng bất kỳ hàm tạo nào, bao gồm một hàm tạo bản sao, trình biên dịch sẽ không ngầm khai báo hoặc định nghĩa một hàm tạo mặc định.

Đây không phải lúc nào cũng là vấn đề.

Nếu bạn không muốn lớp của bạn được cấu hình mặc định, thì tốt nhất là không khai báo một hàm tạo mặc định. Nhưng nếu bạn muốn nó được cấu hình mặc định (ví dụ, nếu bạn muốn bỏ ghi chú dòng X x1; trong ví dụ của bạn), thì bạn phải khai báo và định nghĩa một hàm tạo mặc định. Cũng cần lưu ý rằng một hàm tạo mặc định là bất kỳ hàm tạo nào có thể được gọi không có đối số, không chỉ là một đối số không có đối số. X::X(int = 5) là một hàm tạo mặc định hoàn hảo.

0

1) Constructor không có đối số được gọi là 'Constructor mặc định'. 2) Nếu người dùng không cung cấp bất kỳ hàm tạo nào sau đây, thì trình biên dịch tuyên bố hàm tạo mặc định cho bạn.

2a) Copy Constructor 
    2b) Non-default constructor 
    2C) default constructor. 

3) Nếu trình biên dịch tuyên bố 'constructor mặc định', sau đó nó được gọi là 'ngầm tuyên bố constructor mặc định',

4) 'ngầm tuyên bố constructor mặc định' bao gồm hai loại

4a) **trivial** Constructor 
    4b) **non-trivial** Constructor. 

5) Implictly tuyên bố constructor mặc định được cho là 'tầm thường', khi có 5a) Không tham chiếu biến 5b) Không ảo Chức năng 5c) Không cơ sở ảo class. 5d) Lớp cha mẹ có hàm tạo 'tầm thường',

Else, it is said to be 'non-trivial'. 

Hy vọng điều này sẽ hữu ích.

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