2008-10-02 65 views
13

Tôi nhận thấy một số mã của một đồng nghiệp ngày hôm nay rằng các biến lớp khởi tạo trong khởi tạo. Tuy nhiên nó đã gây ra một cảnh báo, ông nói vì thứ tự mà họ đang ở. Câu hỏi của tôi là tại sao nó tốt hơn để làm khởi tạo biến nơi nó hiện đang và không nằm trong dấu ngoặc nhọn?Khởi tạo lớp C++ chứa khởi tạo biến lớp

DiagramScene::DiagramScene(int slideNo, QRectF screenRect, MainWindow* parent) 
    : QGraphicsScene(screenRect, parent), 
    myParent(parent), 
    slideUndoImageCurrentIndex(-1), 
    nextGroupID(0), 
    m_undoInProgress(false), 
    m_deleteItemOnNextUndo(0) 
    line(0), 
    path(0) 
{ 
    /* Setup default brush for background */ 
    scDetail->bgBrush.setStyle(Qt::SolidPattern); 
    scDetail->bgBrush.setColor(Qt::white); 
    setBackgroundBrush(scDetail->bgBrush); 

} 
+1

Chỉ cần một nhận xét thuật ngữ chung: đây là về biến thành viên. Biến thành viên thuộc về một đối tượng. Biến lớp không tồn tại trong C++, trong khi các biến này có trong ví dụ: Ruby, và phục vụ nhiều hay ít mục đích của các biến thành viên tĩnh C++. – xtofl

Trả lời

26
  • Hiệu quả hơn (nói chung). Tất cả các thành viên của một lớp được khởi tạo trong hàm khởi tạo, cho dù bạn có khởi tạo chúng một cách rõ ràng hay không. Nếu bạn không chỉ định một trình khởi tạo, thì hàm khởi tạo mặc định của thành viên sẽ chạy. Nếu bạn gán một giá trị trong phần thân của hàm tạo, thì toán tử gán được gọi lại. Điều này không áp dụng cho các giá trị vô hướng, như trong ví dụ của bạn, vì các giá trị vô hướng không có các hàm tạo.
  • Bạn không thể vô tình gán giá trị hai lần trong danh sách trình khởi tạo.
  • Trình biên dịch có thể kiểm tra để đảm bảo rằng thứ tự mà bạn viết các initialisers khớp với thứ tự các thành viên được định nghĩa trong lớp. Tiêu chuẩn C++ yêu cầu các thành viên được khởi tạo theo thứ tự mà chúng được khai báo, bất kể thứ tự bạn viết các initialisers. Có trình biên dịch kiểm tra thứ tự này đảm bảo rằng lập trình viên biết thứ tự các initialisers sẽ được chạy trong (một lần nữa, điều này quan trọng hơn đối với các thành viên không phải POD hơn là cho vô hướng).
  • Các loại tham chiếu và const thành viên phải được khởi tạo trong danh sách trình khởi tạo, vì bạn không thể gán cho tham chiếu hoặc cho thành viên const.
2

Bởi vì, trong phần thân của hàm tạo ("trong dấu ngoặc nhọn") các biến thành viên đã được tạo mặc định. Điều đó có thể có một số hàm ý hiệu suất, khi bạn có một biến thành viên của một kiểu có cấu trúc không nhỏ, khi bạn lần đầu tiên có nó được xây dựng mặc định và sau đó bạn gán nó một số giá trị khác trong hàm tạo, khi bạn có thể có cấu trúc tùy chỉnh nó trực tiếp.

Ngoài ra, một số loại có thể không được xây dựng mặc định (ví dụ tham chiếu) và phải được xây dựng trong danh sách khởi tạo.

+0

Cảm ơn, đã thêm ghi chú về tài liệu tham khảo. +1 –

2

Nếu bạn có các biến const, giá trị của chúng không có thể được thiết lập thông qua chuyển nhượng.

Việc khởi tạo cũng hiệu quả hơn một chút khi gán giá trị cho các đối tượng (không được tích hợp hoặc nội tại) vì đối tượng tạm thời không được tạo giống như một nhiệm vụ.

Xem C++ FAQ-Lite để biết thêm chi tiết

4

Nó tốt hơn để thực hiện khởi tạo của các thành viên trong danh sách khởi tạo bởi vì các thành viên sau đó được chỉ khởi tạo một lần. Điều này có thể là một sự khác biệt rất lớn trong hiệu suất (và thậm chí cả hành vi) nếu các thành viên là các lớp học. Nếu các thành viên là tất cả các loại dữ liệu cơ bản không phải là const, không tham chiếu, thì sự khác biệt thường không đáng kể.

LƯU Ý: Có những lúc các danh sách khởi tạo được yêu cầu cho các kiểu dữ liệu cơ bản - đặc biệt nếu loại là hằng số hoặc tham chiếu. Đối với các kiểu này, dữ liệu chỉ có thể được khởi tạo một lần và do đó nó không thể được khởi tạo trong phần thân của hàm tạo. Xem this article để biết thêm thông tin.

Lưu ý rằng thứ tự khởi tạo của các thành viên là thứ tự các thành viên được khai báo trong định nghĩa lớp, không phải thứ tự các thành viên được khai báo trong danh sách khởi tạo. Nếu cảnh báo có thể được sửa bằng cách thay đổi thứ tự của danh sách khởi tạo, thì tôi khuyên bạn nên làm như vậy.

Đó là đề nghị của tôi rằng:

  • Bạn học cách thích danh sách khởi tạo.
  • Đồng nghiệp của bạn hiểu các quy tắc về thứ tự khởi tạo thành viên (và tránh cảnh báo).
3

Ngoài các biến số excellent answer của Greg Hewgill phải được đặt trong danh sách khởi tạo.

+0

Cảm ơn, đã lưu ý thêm về các thành viên const. +1 –

0

Một bổ sung khác cho câu trả lời của Greg: các thành viên thuộc loại không có hàm tạo mặc định phải được khởi tạo trong danh sách khởi tạo.

0

Câu trả lời của Greg Hegwell chứa một số lời khuyên tuyệt vời, nhưng nó không giải thích tại sao trình biên dịch tạo ra cảnh báo.

Khi danh sách khởi tạo của một hàm tạo được xử lý bởi trình biên dịch, các mục được khởi tạo theo thứ tự chúng được khai báo trong khai báo lớp, không theo thứ tự chúng xuất hiện trong danh sách khởi tạo.

Một số trình biên dịch tạo cảnh báo nếu thứ tự trong danh sách trình khởi tạo khác với thứ tự khai báo (vì vậy bạn sẽ không ngạc nhiên khi các mục không được khởi tạo theo thứ tự của danh sách). Bạn không bao gồm tuyên bố lớp học của mình, nhưng đây là nguyên nhân có khả năng xảy ra cảnh báo bạn đang thấy.

Lý do cho hành vi này là các thành viên của lớp phải luôn được khởi tạo theo cùng thứ tự: ngay cả khi lớp có nhiều hơn một hàm tạo (có thể có các thành viên khác nhau trong danh sách khởi tạo của chúng).

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