C++ 从派生类对象调用基类方法
如何从派生类对象调用由派生类重写的基类方法C++ 从派生类对象调用基类方法,c++,inheritance,C++,Inheritance,如何从派生类对象调用由派生类重写的基类方法 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; } 类基{ 公众: v
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;
}
类基{
公众:
void foo(){cout首先派生的应该从Base继承
class Derived : public Base{
也就是说
首先,你们不能让foo处于派生状态
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
首先考虑将foo()
虚拟化
class Base {
public:
virtual ~Base() = default;
virtual void foo() { … }
};
class Derived : public Base {
public:
virtual void foo() override { … }
};
但是,这可以完成以下任务:
int main() {
Derived bar;
bar.Base::foo();
return 0;
}
始终可以(*)使用限定id引用基类的函数:
(Derived::bar
是隐式虚拟的,即使您不使用virtual
关键字,只要它的签名与Base::bar
兼容)
限定id的形式可以是X::Y
,也可以是::Y
。:
前面的部分指定要在哪里查找标识符Y
。在第一种形式中,我们查找X
,然后从X
的上下文中查找Y
。在第二种形式中,我们查找Y
在全局命名空间中
非限定id不包含::
,因此不(自身)指定查找名称的上下文
在表达式b->foo
中,b
和foo
都是非限定ID。b
在当前上下文中查找(在上面的示例中是main
函数)。我们找到局部变量Base*b
。因为b->foo
具有类成员访问的形式,我们从b
(或者更确切地说是*b
)类型的上下文中查找foo
。因此我们从Base
的上下文中查找foo
。我们将找到成员函数void foo()
在Base
中声明,我将其称为Base::foo
对于foo
,我们现在完成了,并调用Base::foo
对于b->bar
,我们首先找到Base::bar
,但它被声明为virtual
。因为它是virtual
,我们执行虚拟分派。这将调用对象类型的类层次结构中的最终函数重写器b
指向。因为b
指向类型的对象>派生的
,最后的重写器是派生的::bar
当从Derived
的上下文中查找名称foo
时,我们将找到Derived::foo
。这就是为什么Derived::foo
被称为隐藏Base::foo
。表达式,例如d.foo()
,或者在Derived
的成员函数中,简单地使用foo()
或This->foo()
,将从派生的上下文中查找
当使用限定id时,我们显式地声明查找名称的位置的上下文。表达式Base::foo
表示我们希望从Base
的上下文中查找名称foo
(例如,它可以查找继承的Base
函数).此外,它还禁用虚拟分派。
因此,d.Base::foo()
将找到Base::foo
并调用它;d.Base::bar()
将找到Base::bar
并调用它
有趣的事实:纯虚拟函数可以有一个实现。它们不能通过虚拟分派调用,因为它们需要被重写。但是,您仍然可以使用限定id调用它们的实现(如果它们有)
#包括
结构基{
虚拟void foo()=0;
};
void Base::foo()
在本例中,可以使用using关键字,也可以使用限定符。此外,请参阅
#包括
阶级基础{
公众:
void foo(bool-bOne,bool-bTwo){std::coutIt最好将其写成bar.Base::foo()
@Mankarse,直到这成为可能。如果将foo()设为虚拟,仍然需要调用bar.Base::foo()
访问基类方法,对吗?@XunYang是的,你可以。在这种情况下,虚拟性是不相关的,但我发现它值得一提。好的,谢谢!实际上我正在使用一组库,它们使用一个非常通用的函数名void Base1::begin(){\\initialization}
,类派生:public Base1,public Base2{…};void-Derived::begin(){\\initialization}
,所以体系结构很遗憾超出了我的能力范围:(我只是想在这里做一个黑客测试:)相关:如果它不是虚拟的,它就不会被覆盖,Derived::foo
而是隐藏Base::foo
@DyP谢谢你知道这很好:)这看起来很像一个设计问题。如果Derived
有自己版本的foo
,那么如果有人在类外调用我发现这个答案可能比接受的答案更有用。你的派生类foo隐藏了基类foo。在这种情况下使用限定符id语法也有效吗?@nurabha你能详细解释一下吗?我不太明白你的问题是什么。实际上,派生类foo并没有被派生类foo覆盖ss foo,但它是隐藏的。如果将基类指针指向派生对象并使用此指针调用foo,则将打印base。base*basePtrToDerived=&bar;basePtrToDerived->foo();@nurabha是的。强制转换到基是调用base::foo
的另一种方法。使用限定id调用基类的函数时,不管派生类中该函数发生了什么,它都可以工作-它可以隐藏,可以重写,可以私有(通过使用Using声明),使用限定id时,您直接访问基类的函数。
class Base {
public:
virtual ~Base() = default;
virtual void foo() { … }
};
class Derived : public Base {
public:
virtual void foo() override { … }
};
int main() {
Derived bar;
bar.Base::foo();
return 0;
}
#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;
}
struct Base {
void foo() { std::cout << "Base::foo\n"; }
virtual void bar() { std::cout << "Base::bar\n"; }
};
struct Derived : Base {
void foo() { std::cout << "Derived::foo\n"; }
virtual void bar() { std::cout << "Derived::bar\n"; }
};
int main() {
Derived d;
Base* b = &d;
b->foo(); // calls Base::foo
b->bar(); // calls Derived::bar
}
#include <iostream>
struct Base {
virtual void foo() = 0;
};
void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }
struct Derived : Base {
virtual void foo() { std::cout << "Derived::foo\n"; }
};
int main() {
Derived d;
d.foo(); // calls Derived::foo
d.Base::foo(); // calls Base::foo
}
#include <iostream>
struct Base {
public:
void public_fun() { std::cout << "Base::public_fun\n"; }
private:
void private_fun() { std::cout << "Base::private_fun\n"; }
};
struct Public_derived : public Base {
public:
void public_fun() { std::cout << "Public_derived::public_fun\n"; }
void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};
struct Private_derived : private Base {
public:
void public_fun() { std::cout << "Private_derived::public_fun\n"; }
void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};
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
}
#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;
}