成員函數的重載、籠罩與隱蔽具體解析。本站提示廣大學習愛好者:(成員函數的重載、籠罩與隱蔽具體解析)文章只能為提供參考,不一定能成為您想要的結果。以下是成員函數的重載、籠罩與隱蔽具體解析正文
1 重載與籠罩
成員函數被重載的特點:
(1)雷同的規模(在統一個類中);
(2)函數名字雷同;
(3)參數分歧;
(4)virtual 症結字無關緊要。
籠罩是指派生類函數籠罩基類函數,特點是:
(1)分歧的規模(分離位於派生類與基類);
(2)函數名字雷同;
(3)參數雷同;
(4)基類函數必需有virtual 症結字。
上面示例中,函數Base::f(int)與Base::f(float)互相重載,而Base::g(void)被Derived::g(void)籠罩。
#include <iostream.h>
class Base
{
public:
void f(int x){ cout << "Base::f(int) " << x << endl; }
void f(float x){ cout << "Base::f(float) " << x << endl; }
virtual void g(void){ cout << "Base::g(void)" << endl;}
};
class Derived : public Base
{
public:
virtual void g(void){ cout << "Derived::g(void)" << endl;}
};
void main(void)
{
Derived d;
Base *pb = &d;
pb->f(42); // Base::f(int) 42
pb->f(3.14f); // Base::f(float) 3.14
pb->g(); // Derived::g(void)
}
2 使人困惑的隱蔽規矩
原來僅僅差別重載與籠罩其實不算艱苦,然則C++的隱蔽規矩使成績龐雜性陡然增長。
這裡“隱蔽”是指派生類的函數屏障了與其同名的基類函數,規矩以下:
(1)假如派生類的函數與基類的函數同名,然則參數分歧。此時,豈論有沒有virtual症結字,基類的函數將被隱蔽(留意別與重載混雜)。
(2)假如派生類的函數與基類的函數同名,而且參數也雷同,然則基類函數沒有virtual症結字。此時,基類的函數被隱蔽(留意別與籠罩混雜)。
上面示例中:
(1)函數Derived::f(float)籠罩了Base::f(float)。
(2)函數Derived::g(int)隱蔽了Base::g(float),而不是重載。
(3)函數Derived::h(float)隱蔽了Base::h(float),而不是籠罩。
#include <iostream.h>
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
};
class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};
據作者考核,許多C++法式員沒無意識到有“隱蔽”這回事。因為熟悉不敷深入,“隱蔽”的產生可謂出沒無常,經常發生使人困惑的成果。
上面示例,bp 和dp 指向統一地址,按理說運轉成果應當是雷同的,可現實並不是如許。
void main(void)
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3 (surprise!)
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
pd->h(3.14f); // Derived::h(float) 3.14
}
3 解脫隱蔽
隱蔽規矩惹起了很多費事。上面示例中,語句pd->f(10)的本意是想挪用函數Base::f(int),然則Base::f(int)不幸被Derived::f(char *)隱蔽了。因為數字10不克不及被隱式地轉化為字符串,所以在編譯時失足。
class Base
{
public:
void f(int x);
};
class Derived : public Base
{
public:
void f(char *str);
};
void Test(void)
{
Derived *pd = new Derived;
pd->f(10); // error
}