tôi có một kết quả mà tôi không mong đợi từ nhiều thừa kế, virtual
phương pháp và con trỏ đến các lớp học cơ sở.Nhiều thừa kế, phương pháp ảo va chạm và gợi ý từ các lớp cơ sở
Với d.getStr()
, khi d
là một trường hợp derived
, phiên bản base_2
được gọi là, như tôi mong đợi.
Với p->getStr()
, khi p
là một con trỏ đến một trường hợp derived
(hoặc một con trỏ đến base_2
trỏ đến một trường hợp derived
), phiên bản base_2
được gọi là, như tôi mong đợi.
Nhưng với p->getStr()
, khi p
là một con trỏ đến một base_1
trỏ đến một trường hợp derived
, phiên bản base_1
được gọi và tôi đã thuyết phục sẽ được gọi là phiên bản base_2
(nhờ các using
và thực tế là getStr()
là virtual
phương pháp) .
Sau đây là một ví dụ đơn giản:
#include <iostream>
struct base_1
{
virtual std::string getStr() const
{ return "string from base 1"; }
};
struct base_2
{
virtual std::string getStr() const
{ return "string from base 2"; }
};
struct derived : public base_1, public base_2
{
using base_2::getStr;
};
int main()
{
derived d;
derived * dp = &d;
base_1 * bp1 = &d;
base_2 * bp2 = &d;
std::cout << "from derived: " << d.getStr() << std::endl;
std::cout << "from derived pointer: " << dp->getStr() << std::endl;
std::cout << "from base_1 pointer: " << bp1->getStr() << std::endl;
std::cout << "from base_2 pointer: " << bp2->getStr() << std::endl;
}
Kết quả là sau
from derived: string from base 2
from derived pointer: string from base 2
from base_1 pointer: string from base 1
from base_2 pointer: string from base 2
Tôi biết rằng, để áp đặt cuộc gọi của phiên bản base_2
, tôi có thể thêm vào derived
các phương pháp sau đây
std::string getStr() const
{ return base_2::getStr(); }
nhưng câu hỏi của tôi là:
1) Tại sao con trỏ đến base_1
(trỏ đến một thể hiện có nguồn gốc) bỏ qua chỉ thị using
và gọi phiên bản base_1
của getStr()
?
2) Có cách nào để áp đặt các phiên bản base_2
của getStr()
, khi derived
dụ được sử dụng bởi một con trỏ base_1
, mà không cần xác định lại getStr()
?
--- EDIT ---
Cảm ơn câu trả lời.
tôi hiểu rằng bạn đang mô tả những gì đang xảy ra nhưng nghi ngờ của tôi là: không ngôn ngữ (tiêu chuẩn) mô tả khía cạnh này? Hay nó là một phần không xác định?
tôi muốn nói: nếu tôi loại bỏ các chỉ thị using
, tôi nhận được một lỗi biên dịch (error: request for member getStr is ambiguous
), từ d.getStr()
và từ dp->getStr()
, bởi vì trình biên dịch không biết phiên bản nào của getStr()
để chọn.
Nhưng getStr()
là virtual
phương pháp. Vì vậy, (tôi đã bị thuyết phục rằng) một con trỏ cơ sở nên sử dụng phiên bản có nguồn gốc của họ. Nhưng chúng tôi có một vài phương pháp va chạm.
Từ quan điểm ngôn ngữ (tiêu chuẩn), base_1
(hoặc base_2
) là con trỏ được ủy quyền (hoặc bắt buộc) để chọn một trong hai phiên bản của phương thức va chạm bỏ qua phương thức khác?
Có lẽ tôi sai nhưng dường như với tôi rằng, theo cách này, phương pháp virtual
được quản lý như phương pháp không virtual
.
'using' chỉ giúp hiển thị. Nó không làm cho 'overload' bắt nguồn từ hàm ảo cơ sở hoặc trông giống như nó. – Arunmu