trả lời ngắn: Có bạn sẽ cần phải lặp lại công việc trong D
Long trả lời:
Nếu lớp có nguồn gốc của 'D' không chứa các biến thành viên mới thì phiên bản mặc định (được tạo ra bởi trình biên dịch nên làm việc tốt). Trình tạo bản sao mặc định sẽ gọi hàm tạo bản sao gốc và toán tử gán mặc định sẽ gọi toán tử gán cha.
Nhưng nếu lớp học 'D' của bạn chứa tài nguyên thì bạn sẽ cần thực hiện một số công việc.
tôi thấy nhà xây dựng bản sao của bạn một chút lạ:
B(const B& b){(*this) = b;}
D(const D& d){(*this) = d;}
thường copy constructor chuỗi để họ được copy xây dựng từ cơ sở lên. Ở đây bởi vì bạn đang gọi toán tử gán, hàm tạo bản sao phải gọi hàm khởi tạo mặc định để khởi tạo mặc định đối tượng từ dưới lên trước. Sau đó, bạn đi xuống một lần nữa bằng cách sử dụng toán tử gán. Điều này có vẻ không hiệu quả.
Bây giờ nếu bạn thực hiện một nhiệm vụ bạn đang sao chép từ dưới lên (hoặc trên xuống) nhưng có vẻ như khó khăn cho bạn để làm điều đó và cung cấp một bảo đảm ngoại lệ mạnh mẽ. Nếu tại bất kỳ điểm nào một tài nguyên không sao chép và bạn ném một ngoại lệ đối tượng sẽ ở trong trạng thái không xác định (đó là một điều xấu).
Thông thường tôi đã thấy nó được thực hiện theo cách khác.
Toán tử gán được xác định theo điều khoản của hàm tạo bản sao và trao đổi. Điều này là bởi vì nó làm cho nó dễ dàng hơn để cung cấp bảo đảm ngoại lệ mạnh mẽ. Tôi không nghĩ rằng bạn sẽ có thể cung cấp đảm bảo mạnh mẽ bằng cách làm theo cách này xung quanh (tôi có thể sai).
class X
{
// If your class has no resources then use the default version.
// Dynamically allocated memory is a resource.
// If any members have a constructor that throws then you will need to
// write your owen version of these to make it exception safe.
X(X const& copy)
// Do most of the work here in the initializer list
{ /* Do some Work Here */}
X& operator=(X const& copy)
{
X tmp(copy); // All resource all allocation happens here.
// If this fails the copy will throw an exception
// and 'this' object is unaffected by the exception.
swap(tmp);
return *this;
}
// swap is usually trivial to implement
// and you should easily be able to provide the no-throw guarantee.
void swap(X& s) throws()
{
/* Swap all members */
}
};
Thậm chí nếu bạn lấy được một lớp D từ X thì điều này không ảnh hưởng đến mẫu này.
Phải thừa nhận rằng bạn cần phải lặp lại một chút công việc bằng cách thực hiện các cuộc gọi rõ ràng vào lớp cơ sở, nhưng điều này là tương đối nhỏ.
class D: public X
{
// Note:
// If D contains no members and only a new version of foo()
// Then the default version of these will work fine.
D(D const& copy)
:X(copy) // Chain X's copy constructor
// Do most of D's work here in the initializer list
{ /* More here */}
D& operator=(D const& copy)
{
D tmp(copy); // All resource all allocation happens here.
// If this fails the copy will throw an exception
// and 'this' object is unaffected by the exception.
swap(tmp);
return *this;
}
// swap is usually trivial to implement
// and you should easily be able to provide the no-throw guarantee.
void swap(D& s) throws()
{
X::swap(s); // swap the base class members
/* Swap all D members */
}
};
Nguồn
2009-08-04 10:39:10
Nếu bạn chỉ muốn ghi đè phương thức 'foo', bạn có thể sử dụng' using B :: operator =; 'để kế thừa toán tử gán, nhưng sao chép và di chuyển các hàm tạo không thể được kế thừa: https://stackoverflow.com/q/49045026/5447906 –