Call base class method from derived class object
如何从派生类对象调用由派生类重写的基类方法?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Base{ public: void foo(){cout<<"base";} }; class Derived:public Base{ public: void foo(){cout<<"derived";} } int main(){ Derived bar; //call Base::foo() from bar here? return 0; } |
通过使用限定ID,可以始终(*)引用基类的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> class Base{ public: void foo(){std::cout<<"base";} }; class Derived : public Base { public: void foo(){std::cout<<"derived";} }; int main() { Derived bar; //call Base::foo() from bar here? bar.Base::foo(); // using a qualified-id return 0; } |
[也修正了一些操作错误]
(*)访问限制仍然适用,基类可能不明确。
如果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | struct Base { void foo() { std::cout <<"Base::foo "; } virtual void bar() { std::cout <<"Base::bar "; } }; struct Derived : Base { void foo() { std::cout <<"Derived::foo "; } virtual void bar() { std::cout <<"Derived::bar "; } }; int main() { Derived d; Base* b = &d; b->foo(); // calls Base::foo b->bar(); // calls Derived::bar } |
(即使不使用
限定ID的形式可以是
非限定ID不包含
在表达
对于
对于
从
当使用限定ID时,我们显式地声明在何处查找名称的上下文。表达式
因此,
有趣的事实:纯虚拟函数可以有一个实现。不能通过虚拟调度调用它们,因为它们需要被重写。但是,您仍然可以使用限定ID调用它们的实现(如果它们有实现的话)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream> struct Base { virtual void foo() = 0; }; void Base::foo() { std::cout <<"look ma, I'm pure virtual! "; } struct Derived : Base { virtual void foo() { std::cout <<"Derived::foo "; } }; int main() { Derived d; d.foo(); // calls Derived::foo d.Base::foo(); // calls Base::foo } |
请注意,类成员和基类的访问说明符都会影响您是否可以使用限定ID在派生类型的对象上调用基类的函数。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <iostream> struct Base { public: void public_fun() { std::cout <<"Base::public_fun "; } private: void private_fun() { std::cout <<"Base::private_fun "; } }; struct Public_derived : public Base { public: void public_fun() { std::cout <<"Public_derived::public_fun "; } void private_fun() { std::cout <<"Public_derived::private_fun "; } }; struct Private_derived : private Base { public: void public_fun() { std::cout <<"Private_derived::public_fun "; } void private_fun() { std::cout <<"Private_derived::private_fun "; } }; int main() { Public_derived p; p.public_fun(); // allowed, calls Public_derived::public_fun p.private_fun(); // allowed, calls Public_derived::public_fun p.Base::public_fun(); // allowed, calls Base::public_fun p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun Private_derived r; r.Base::public_fun(); // NOT allowed, tries to call Base::public_fun r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun } |
可访问性与名称查找是正交的。因此,名称隐藏不会对其产生影响(您可以在派生类中省略
首先,派生的应该从基继承。
1 | class Derived : public Base{ |
那说
首先,你们不能在派生的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Base{ public: void foo(){cout<<"base";} }; class Derived : public Base{ } int main(){ Derived bar; bar.foo() // calls Base::foo() return 0; } |
其次,您可以使派生::foo调用base::foo。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Base{ public: void foo(){cout<<"base";} }; class Derived : public Base{ public: void foo(){ Base::foo(); } ^^^^^^^^^^ } int main(){ Derived bar; bar.foo() // calls Base::foo() return 0; } |
第三,可以使用base::foo的限定ID
1 2 3 4 5 | int main(){ Derived bar; bar.Base::foo(); // calls Base::foo() return 0; } |
首先考虑使
1 2 3 4 5 6 7 8 9 10 11 | class Base { public: virtual ~Base() = default; virtual void foo() { … } }; class Derived : public Base { public: virtual void foo() override { … } }; |
但是,这样做的目的是:
1 2 3 4 5 | int main() { Derived bar; bar.Base::foo(); return 0; } |
一个重要的[附加]注意:如果发生名称隐藏,您仍然会有编译错误。
在这种情况下,要么使用using关键字,要么使用qualifer。另外,也可以看到这个答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> class Base{ public: void foo(bool bOne, bool bTwo){std::cout<<"base"<<bOne<<bTwo;} }; class Derived : public Base { public: void foo(bool bOne){std::cout<<"derived"<<bOne;} }; int main() { Derived bar; //bar.foo(true,true); // error: derived func attempted bar.foo(true); // no error: derived func bar.Base::foo(true,true); // no error: base func, qualified return 0; } |