2011-01-26 20 views
5

CÂU HỎI 1)C++ Cơ sở constructor gọi với tham số đó sẽ được xây dựng trong các nhà xây dựng có nguồn gốc

class Base { 
    Base(std::string name); 

    virtual std::string generateName(); 
} 

class Derived : Base { 
    Derived(); 

    virtual std::string generateName(); 
} 

ở đây có các câu hỏi:

phương pháp gì sẽ được kêu gọi generateName()?

Derived :: Derived : Base(generateName()) { 
    //what method will be called on generateName() ? 
} 

CÂU HỎI 2)

làm thế nào tôi nên làm cho nó? nếu constructor mặc định phải chấp nhận một tham số, nhưng tôi cần phải tạo tham số đó trong hàm tạo Derived?

Trả lời

8

Đầu tiên, giải pháp: sử dụng hàm thành viên tĩnh hoặc chức năng không phải là thành viên.

Đối với hành vi, Derived::generateName() sẽ được gọi. Câu dài trong tiêu chuẩn C++ xác định hành vi này nói (C++ 03 12.7/3):

Khi hàm ảo được gọi trực tiếp hoặc gián tiếp từ một hàm tạo (bao gồm từ bộ khởi tạo mem cho dữ liệu thành viên) hoặc đối tượng mà cuộc gọi áp dụng là đối tượng đang được xây dựng hoặc hủy, hàm được gọi là đối tượng được định nghĩa trong hàm tạo hoặc lớp riêng của trình phá hủy hoặc một trong các cơ sở của nó, nhưng không phải là chức năng ghi đè nó trong một lớp có nguồn gốc từ lớp khởi tạo hoặc lớp hủy, hoặc ghi đè nó trong một trong các lớp cơ sở khác của đối tượng được sinh ra nhiều nhất.

Bởi vì hàm tạo đang được thực hiện tại thời điểm cuộc gọi ảo là một hàm tạo Derived, được gọi là Derived::generateName().

Câu trả lời bị xóa ngay được đề cập đến một bài viết của Scott Meyers đề xuất "Never Call Virtual Functions during Construction or Destruction." Quy tắc cho những gì người gọi được gọi là phức tạp và khó nhớ.

+3

Điều này sẽ đúng nếu 'generateName()' được gọi từ * bên trong * 'Base :: Base'. Nhưng ở đây, chúng ta đang gọi nó trong danh sách khởi tạo, trước khi chúng ta nhập 'Base :: Base'. Điều này vẫn đúng? –

+0

Ah, bạn đã cập nhật câu trả lời của mình. Điều này cảm thấy ngay bây giờ, vì vậy +1. –

+1

@Oli: Không. Tôi đã sai và đã sửa câu trả lời sau khi nghiên cứu vấn đề và chạy một số thử nghiệm. Tôi thực sự hơi ngạc nhiên bởi hành vi được chỉ định. Nó cảm thấy sai với tôi ;-) (Nó phá vỡ mô hình mà tôi thường sử dụng để lý luận về các cuộc gọi chức năng ảo trong quá trình xây dựng và bây giờ tôi phải quay lại và tìm tất cả các câu trả lời trong đó tôi đã mô tả sai quá trình .. .) Cảm ơn bạn đã đặt câu hỏi về câu trả lời gốc. –

1

Hãy hai ...

tôi đã làm một hoạt động với các cuộc gọi đến generateName() trong initialiser lớp cơ sở và cả nhà xây dựng. Sản lượng để lại cho tôi không bị nhiễu:

Derived (called from Derived's Base initializer) 
Base (called from Base ctor) 
Derived (called from Derived ctor) 

Tôi chưa bao giờ tưởng tượng rằng một lớp có thể biến đổi thành nguồn gốc, sau đó quay lại xuất phát trong một chuỗi xây dựng duy nhất. Bạn học được điều gì mới mỗi ngày.

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