[英]c++ polymorphism, name resolution for derived class
class Base {
public:
virtual void f(float) { cout << "Base::f(float)\n"; }
};
class Derived : public Base {
public:
virtual void f(int) { cout << "Derived::f(int)\n"; }
};
int main() {
Derived *d = new Derived();
Base *b = d;
b->f(3.14F);
d->f(3.14F);
}
-C ++不支持contravaraint返回類型,因此f(int)不會覆蓋f(float)
-Polymorphism由C ++支持,因此d和b都應指向派生類的vtable。
派生類的-vtable類似於0:f(float),1:f(int)等。
我對這個問題的回答是Base :: f(float)被調用兩次,但答案是:
Base :: f(float)Derived :: f(int)
為什么會這樣? 從不同的指針訪問派生類是否強制執行某些規則? 據我所知,對象切片僅在使用copy-ctor或copy-assignment時發生,使用指針,它們都應指向相同的vtable。
不同類中的方法不會一起重載; 在Derived
定義另一個f()
可以防止在重載過程中考慮Base
那個。
如果要添加新的重載而不隱藏基類中定義的重載,則需要將基本定義顯式引入派生類。
public:
using Base::f;
我對此的看法是,當你調用d->f(3.14F)
float隱式轉換為int
你的Derived
類實際上有兩個f()項
void f(int);
void f(float);
使用帶有-fdump-class-hierarchy標志的g ++確認了這一點。 我們可以看到輸出如下:
Vtable for Base
Base::_ZTV4Base: 3u entries
0 (int (*)(...))0
4 (int (*)(...))(& _ZTI4Base)
8 (int (*)(...))Base::f
Vtable for Derived
Derived::_ZTV7Derived: 4u entries
0 (int (*)(...))0
4 (int (*)(...))(& _ZTI7Derived)
8 (int (*)(...))Base::f
12 (int (*)(...))Derived::f
由於定義不匹配, Derived
類不會觸及基類中的f函數。 代碼編譯是因為float和int之間存在隱式轉換。
請嘗試以下方法
class Derived : public Base {
public:
virtual void f(std::string) { cout << "Derived::f(string)\n"; }
};
然后這段代碼將不會編譯為Derived:f(...)將隱藏Base :: f(...)定義。 這通常稱為繼承陰影。
因此調用b-> f(3.14F)將在Base表中解析,d-> f(3.14F)將使用Derived表解析,該表將影響Base。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.