Eri*_*Luo 24 c++ inheritance private
我对以下关于继承的小程序感到困惑:
#include<iostream>
using namespace std;
struct B {
virtual int f() { return 1; }
}; // f is public in B
class D : public B {
int f() { return 2; }
}; // f is private in D
int main()
{
D d;
B& b = d;
cout<<b.f()<<endl; // OK: B::f() is public, D::f() is invoked even though it's private
cout<<d.f()<<endl; // error: D::f() is private
}
Run Code Online (Sandbox Code Playgroud)
D::f()是私有的,D是公共继承从B,所以公共职能f中BD(我知道没有继承,成员访问是私人默认)f是一个虚函数B,所以如果我们打电话b.f(),我们实际上打电话D::f(),但正如图中所提到的,为什么D::f()即使它是私人的,也可以被调用?任何人都可以详细解释简单的继承问题吗?
Gui*_*cot 21
这必须做到这一点,虚拟调度是一个运行时概念.该类B并不关心哪个类扩展它,并且它不关心它是私有的还是公共的,因为它无法知道.
我无法弄清楚为什么D :: f()是私有的,D是公共继承自B,因此B中的公共函数f在D中也是公共的(我知道没有继承,默认情况下成员访问是私有的)
D::f()是私人的,因为你把它变成了私人.此规则不受继承或虚拟分派的影响.
f是B中的虚函数,所以如果我们调用bf(),我们实际调用D :: f(),但正如图中所提到的,为什么D :: f()能够被调用,即使它是私有的?
因为实际上,在调用时b.f(),编译器不知道实际调用哪个函数.它将简单地调用该函数f(),并且由于它B::f是虚拟的,因此将在运行时选择被调用的函数.运行时程序没有关于哪个功能是私有还是受保护的信息.它只知道功能.
如果在运行时选择了该函数,则编译器无法在编译时知道将调用哪个函数,并且无法知道访问说明符.实际上,编译器甚至不会尝试检查被调用的函数是否是私有的.访问说明符可能在编译器还没有看到的某些代码中.
如您所见,您不能D::f直接打电话.这正是私人所做的:禁止直接访问会员.但是,您可以通过指针或引用间接访问它.您使用的虚拟调度将在内部执行.
M.M*_*M.M 11
访问说明符仅适用于函数名称,它们对通过其他方式调用函数的方式或时间没有一些限制.如果通过除名称之外的某些方式(例如,函数指针)使私有函数可用,则可以在类外部调用私函数.
对于使用classkeyword 声明的类,默认的访问说明符是private.您的代码与以下内容相同:
// ...
class D: public B
{
private:
int f() { return 2; }
};
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,f是私人的D.对于B具有相同名称的任何函数,访问说明符的含义没有区别.在你的头脑是清楚的B::f(),并D::f()有两种不同的功能.
virtual关键字的作用是,如果f()没有在B引用D对象的引用上调用范围限定符,那么即使它解析为B::f(),实际上D::f()也会调用它.
此过程仍然使用访问说明符B::f():在编译时检查访问; 但是关于调用哪个函数可能是运行时间问题.
C++标准有一个确切的例子:
11.5访问虚函数[class.access.virt]
1虚函数的访问规则(第11条)由其声明确定,不受稍后覆盖它的函数规则的影响.[ 例如:
Run Code Online (Sandbox Code Playgroud)class B { public: virtual int f(); }; class D : public B { private: int f(); }; void f() { D d; B* pb = &d; D* pd = &d; pb->f(); // OK: B::f() is public, // D::f() is invoked pd->f(); // error: D::f() is private }- 结束例子 ]
无法解释清楚.
给出的答案说明了正在做什么,但为什么你会想要这样做,基类调用private虚函数?
好吧,有一种称为模板方法模式的设计模式 ,它使用这种技术,它具有一个在派生类中调用私有虚函数的基类.
struct B
{
virtual ~B() {};
int do_some_algorithm()
{
do_step_1();
do_step_2();
do_step_3();
}
private:
virtual void do_step_1() {}
virtual void do_step_2() {}
virtual void do_step_3() {}
};
class D : public B
{
void do_step_1()
{
// custom implementation
}
void do_step_2()
{
// custom implementation
}
void do_step_3()
{
// custom implementation
}
};
int main()
{
D dInstance;
B * pB = &dInstance;
pB->do_some_algorithm();
}
Run Code Online (Sandbox Code Playgroud)
这允许我们不将类的自定义步骤暴露D给public接口,但同时允许B使用public函数调用这些函数.
| 归档时间: |
|
| 查看次数: |
4064 次 |
| 最近记录: |