2010-01-18 15 views
11

Tôi có hai lớpLàm thế nào để bạn sử dụng hàm tạo không mặc định cho một thành viên?

class a { 
    public: 
     a(int i); 
}; 

class b { 
    public: 
     b(); //Gives me an error here, because it tries to find constructor a::a() 
     a aInstance; 
} 

Làm thế nào tôi có thể lấy nó để aInstance được khởi tạo với một (int i) thay vì cố gắng tìm kiếm một constructor mặc định? Về cơ bản, tôi muốn kiểm soát việc gọi hàm dựng của từ bên trong hàm tạo của b.

+0

Tôi nhận ra đây là một ví dụ chứ không phải mã thực sự, nhưng chỉ vì lợi ích của ~~ là một chất lượng mã vạch ~ ~, thường không phải là một ý tưởng hay để tạo trường 'công khai'. Chắc chắn, có một số trường hợp sử dụng và không phải là _universally_ xấu, nhưng trước khi thực hiện, hãy đảm bảo có lý do ngoài "nó có thể đơn giản hóa một số mã của tôi" ("nó đơn giản hóa rất nhiều mã của tôi" là lý do hoàn toàn có thể chấp nhận được) , mặc dù) –

Trả lời

20

Bạn cần phải gọi một (int) một cách rõ ràng trong danh sách constructor khởi tạo:

b() : aInstance(3) {} 

đâu 3 là giá trị ban đầu mà bạn muốn sử dụng. Mặc dù nó có thể là bất kỳ int. Xem nhận xét cho các lưu ý quan trọng về trật tự và các lưu ý khác.

+0

Cảm ơn rất nhiều. Tôi nghĩ rằng đó chỉ là để gọi các nhà xây dựng lớp cha mẹ. –

+1

Đúng, bạn cũng có thể sử dụng nó để khởi tạo thành viên. –

+0

Trong một số trường hợp, bạn phải khởi tạo thành viên (tham khảo, ví dụ), và đây là cách bạn làm điều đó. –

3

Sử dụng một danh sách khởi tạo:

b::b() : aInstance(1) {} 
0

Chỉ cần sử dụng một constructor được định nghĩa như thế này:

class b { 
public: 
    b() 
    : aInstance(5) 
    {} 
    a aInstance; 
}; 
+1

Đây không phải là hợp lệ C++. –

+1

Với biến thành viên, điều này sẽ chỉ hoạt động nếu biến là 'static const', như trong' static const int x (3); ' –

+0

Tôi thực sự cần lưu ý rằng tôi không truyền một hằng số cho hàm tạo, nhưng thành viên của b. Khi tôi cố gắng làm a aInstance (c); nó diễn giải đó dưới dạng định nghĩa hàm. –

-2

Tôi nghĩ rằng bạn nên sử dụng một con trỏ đến 'a' như:

class b { 
public: 
    b() : aInstance(new a(5)) {} 
    a *aInstance; 
}; 

Bằng cách này, bạn sẽ có hành vi được xác định. Tất nhiên bạn sẽ cần phải giải phóng * aInstance trong destructor.

+1

Phân bổ đống là rất nhiều không được ưu tiên để phân bổ stack. Mã của bạn hiện đang thiếu một trình tạo bản sao, toán tử gán và hàm hủy. – GManNickG

+1

Tôi đồng ý. Tôi hơi quá nhanh với bình luận của tôi, đặc biệt vì aInstance chỉ là một vật nhỏ. Tôi đã suy nghĩ về các tình huống thực tế trong đó các đối tượng có thể lớn hơn, nơi bạn có thể có khởi tạo lười biếng, v.v .. Tôi đoán tôi đã làm quá nhiều C# và Java gần đây, nơi hầu hết mọi thứ được thực hiện bằng cách tham chiếu;) –