Tại sao tôi không thể làm điều này?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Tại sao tôi không thể làm điều này?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
Câu trả lời:
Bạn không thể khởi tạo a
và đăng b
nhập B
vì họ không phải là thành viên của B
. Họ là thành viên của A
, do đó chỉ A
có thể khởi tạo chúng. Bạn có thể đặt chúng ở chế độ công khai, sau đó thực hiện chuyển nhượng B
, nhưng đó không phải là một tùy chọn được khuyến nghị vì nó sẽ phá hủy tính năng đóng gói. Thay vào đó, hãy tạo một phương thức khởi tạo A
để cho phép B
(hoặc bất kỳ lớp con nào của A
) khởi tạo chúng:
class A
{
protected:
A(int a, int b) : a(a), b(b) {} // Accessible to derived classes
// Change "protected" to "public" to allow others to instantiate A.
private:
int a, b; // Keep these variables private in A
};
class B : public A
{
public:
B() : A(0, 0) // Calls A's constructor, initializing a and b in A to 0.
{
}
};
a
và b
vào B::B()
vì chúng ở chế độ riêng tư. Bạn không thể khởi tạo chúng vì chúng không phải là thành viên của class B
. Nếu bạn đặt chúng ở chế độ công khai hoặc được bảo vệ, bạn có thể chỉ định chúng trong phần nội dung của B::B()
.
a
và b
..." và thay đổi thành "Bạn không thể khởi tạo ..." mà không đảm bảo phần còn lại của câu có ý nghĩa. Đã chỉnh sửa bài đăng.
Bỏ qua một thực tế rằng chúng private
, vì a
và b
là thành viên của A
, chúng được khởi tạo bởi các hàm tạo của A
', không phải bởi các hàm tạo của một số lớp khác (dẫn xuất hay không).
Thử:
class A
{
int a, b;
protected: // or public:
A(int a, int b): a(a), b(b) {}
};
class B : public A
{
B() : A(0, 0) {}
};
Bằng cách nào đó, không ai liệt kê cách đơn giản nhất:
class A
{
public:
int a, b;
};
class B : public A
{
B()
{
a = 0;
b = 0;
}
};
Bạn không thể truy cập các thành viên cơ sở trong danh sách trình khởi tạo, nhưng chính phương thức khởi tạo, cũng như bất kỳ phương thức thành viên nào khác, có thể truy cập public
và protected
các thành viên của lớp cơ sở.
B
được cấp phát, sau đó nó sẽ được gán bên trong hàm tạo B
của. Nhưng tôi cũng nghĩ rằng trình biên dịch vẫn có thể tối ưu hóa điều này.
class A
chúng ta không thể dựa vào a
và b
được khởi tạo. class C : public A
Ví dụ: bất kỳ triển khai nào của có thể quên gọi a=0;
và để lại trạng thái a
chưa khởi tạo.
class A { int a = 0;};
) hoặc trong hàm tạo của lớp cơ sở. Các lớp con vẫn có thể khởi tạo lại chúng trong phương thức khởi tạo của chúng khi cần thiết.
# include<stdio.h>
# include<iostream>
# include<conio.h>
using namespace std;
class Base{
public:
Base(int i, float f, double d): i(i), f(f), d(d)
{
}
virtual void Show()=0;
protected:
int i;
float f;
double d;
};
class Derived: public Base{
public:
Derived(int i, float f, double d): Base( i, f, d)
{
}
void Show()
{
cout<< "int i = "<<i<<endl<<"float f = "<<f<<endl <<"double d = "<<d<<endl;
}
};
int main(){
Base * b = new Derived(10, 1.2, 3.89);
b->Show();
return 0;
}
Đây là một ví dụ hoạt động trong trường hợp bạn muốn khởi tạo các thành viên dữ liệu lớp Cơ sở có trong đối tượng lớp Derived, trong khi bạn muốn đẩy các giá trị này giao tiếp thông qua lệnh gọi phương thức khởi tạo lớp Derived.
Mặc dù điều này hữu ích trong một số trường hợp hiếm hoi (nếu không phải như vậy, ngôn ngữ sẽ cho phép nó trực tiếp), hãy xem thành ngữ Cơ sở từ Thành viên . Nó không phải là một giải pháp miễn phí về mã, bạn sẽ phải thêm một lớp kế thừa bổ sung, nhưng nó sẽ hoàn thành công việc. Để tránh mã viết sẵn, bạn có thể sử dụng triển khai của boost
Tại sao bạn không làm được? Bởi vì ngôn ngữ không cho phép bạn khởi tạo danh sách khởi tạo 'các thành viên trong lớp dẫn xuất' của lớp cơ sở.
Làm thế nào bạn có thể hoàn thành việc này? Như thế này:
class A
{
public:
A(int a, int b) : a_(a), b_(b) {};
int a_, b_;
};
class B : public A
{
public:
B() : A(0,0)
{
}
};
Nếu bạn không chỉ định khả năng hiển thị cho một thành viên trong lớp, nó sẽ mặc định là "riêng tư". Bạn nên đặt các thành viên của mình ở chế độ riêng tư hoặc được bảo vệ nếu bạn muốn truy cập họ trong một lớp con.
Các lớp tổng hợp, như A trong ví dụ (*) của bạn, phải có các thành viên của chúng là công khai và không có hàm tạo do người dùng xác định. Chúng được phức tạp hóa với danh sách trình khởi tạo, ví dụ A a {0,0};
hoặc trong trường hợp của bạn B() : A({0,0}){}
. Các thành viên của lớp tổng hợp cơ sở không thể được khởi tạo riêng lẻ trong phương thức khởi tạo của lớp dẫn xuất.
(*) Nói một cách chính xác, như đã đề cập một cách chính xác, bản gốc class A
không phải là tổng hợp do các thành viên riêng tư không tĩnh