C++从派生类调用基类

1、如何从派生类对象调用派生类覆盖的基类方法?
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;
}

2、您可以使用qualified-id来始终(*)引用基类的函数:
#include
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;
}

3、()访问限制仍然适用,基类可能是模糊的。如果Base :: foo不是虚拟的,那么Derived :: foo不会覆盖Base :: foo。相反,Derived :: foo隐藏了Base :: foo。以下示例可以看出差异:
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
}
(Derived :: bar是隐式虚拟的,即使你不使用virtual关键字,只要它的签名与Base :: bar兼容)。
一个qualified-id是X :: Y或者:: Y的形式。在::之前的部分指定了我们要查找标识符Y的位置。在第一种形式中,我们查找X,然后我们查找Y来自X的上下文。在第二种形式中,我们在全局命名空间中查找Y。
unqualified-id不包含一个::,因此(本身)不指定查找名称的上下文。在表达式b→foo中,b和foo都是不合格的。 b在当前上下文中查找(在上面的示例中是主要功能)。我们找到局部变量Base * b。因为b-> foo具有类成员访问的形式,所以我们从b类型(或* b)的上下文中查找foo。所以我们从Base的上下文中查找foo。我们将在Base中找到成员函数void foo(),我将引用为Base :: foo。对于foo,我们现在完成了,并调用Base :: foo。对于b-> bar,我们首先找到Base :: bar,但它被声明为虚拟。因为它是虚拟的,我们执行一个虚拟调度。这将调用对象b类型的类层次结构中的final函数覆盖。因为b指向Derived类型的对象,所以最终的覆盖者是Derived :: bar。从Derived的上下文中查找名称foo时,我们会发现Derived :: foo。这就是为什么Derived :: foo被隐藏为Base :: foo。在Derived的成员函数中使用简单的foo()或this-> foo()的表达式将从Derived的上下文中查找。当使用qualified-id时,我们明确指出在哪里查找名称的上下文。 Base :: foo表示我们要从Base的上下文中查找名字foo(例如,可以找到Base继承的函数)。另外,它禁用虚拟调度。
因此,d.Base :: foo()将找到Base :: foo并调用它; d.Base :: bar()将找到Base :: bar并调用它。

4、纯虚拟功能可以实现。它们不能通过虚拟调度进行调用,因为它们需要被覆盖。但是,您仍然可以通过使用qualified-id来调用它们的实现(如果有的话)。
#include
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
}
类成员和基类的访问说明符对于是否可以使用限定id来对派生类型的对象调用基类的函数有影响。
#include
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::private_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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值