เป็นเพราะการค้นหาชื่อจะหยุดลงหากพบชื่อในฐานใดฐานหนึ่งของคุณ มันจะไม่ดูเกินกว่าในฐานอื่น ๆ ฟังก์ชันใน B ทำเงาฟังก์ชันใน A คุณต้องประกาศฟังก์ชันของ A อีกครั้งในขอบเขตของ B เพื่อให้ทั้งสองฟังก์ชันสามารถมองเห็นได้จากภายใน B และ C:
class A
{
public:
void foo(string s){};
};
class B : public A
{
public:
int foo(int i){};
using A::foo;
};
class C : public B
{
public:
void bar()
{
string s;
foo(s);
}
};
แก้ไข: คำอธิบายที่แท้จริงที่มาตรฐานให้คือ (จาก 10.2 / 2):
ขั้นตอนต่อไปนี้กำหนดผลลัพธ์ของการค้นหาชื่อในขอบเขตคลาส C. ขั้นแรกทุกการประกาศสำหรับชื่อในคลาสและในแต่ละอ็อบเจ็กต์ย่อยของคลาสพื้นฐานจะถูกพิจารณา ชื่อสมาชิก f ในอ็อบเจ็กต์ย่อยหนึ่ง B ซ่อนชื่อสมาชิก f ในอ็อบเจ็กต์ย่อย A ถ้า A เป็นอ็อบเจ็กต์ย่อยคลาสพื้นฐานของ B การประกาศใด ๆ ที่ซ่อนอยู่จะถูกตัดออกจากการพิจารณา การประกาศเหล่านี้แต่ละรายการที่นำมาใช้โดยการประกาศใช้ถือว่ามาจากวัตถุย่อยแต่ละรายการของ C ที่เป็นประเภทที่มีการประกาศที่กำหนดโดยการประกาศใช้ 96) หากชุดการประกาศผลลัพธ์ไม่ใช่ ทั้งหมดมาจากอ็อบเจ็กต์ย่อยประเภทเดียวกันหรือเซ็ตมีสมาชิกที่ไม่หยุดนิ่งและรวมถึงสมาชิกจากอ็อบเจ็กต์ย่อยที่แตกต่างกันมีความคลุมเครือและโปรแกรมมีรูปแบบไม่ถูกต้อง มิฉะนั้นชุดนั้นจะเป็นผลมาจากการค้นหา
มันมีสิ่งต่อไปนี้ที่จะพูดในที่อื่น (ด้านบน)
สำหรับ id-expression [ บางอย่างเช่น "foo" ] การค้นหาชื่อจะเริ่มต้นในขอบเขตคลาสของสิ่งนี้ สำหรับ ID ที่ผ่านการรับรอง [ เช่น "A :: foo", A คือตัวระบุชื่อที่ซ้อนกัน ] การค้นหาชื่อจะเริ่มต้นในขอบเขตของตัวระบุชื่อที่ซ้อนกัน การค้นหาชื่อจะเกิดขึ้นก่อนการควบคุมการเข้าถึง (3.4 ข้อ 11)
([... ] ใส่โดยฉัน). โปรดทราบว่าหมายความว่าแม้ว่า foo ของคุณใน B จะเป็นแบบส่วนตัว แต่ foo ใน A จะยังไม่พบ (เนื่องจากการควบคุมการเข้าถึงจะเกิดขึ้นในภายหลัง)