[英]Private virtual function of base is hidden by private virtual function of derived
[英]Override public virtual function with private base function?
让我们考虑具有以下接口的两个类A
和B
:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
然后是第三个继承自两者的类, A
公开,因为它实现了这个“接口”, B
私有,因为这是实现细节。
然而,在这个特定的实现中, start()
只需要包含对B::start()
的调用。 所以我想我可以使用快捷方式并执行以下操作:
class C: public A, private B {
public:
using B::start;
};
并完成它,但显然它不起作用。 因此,我无法using
私有基函数来覆盖虚拟。 由此,两个问题:
start()
函数在C
具有完全相同的签名,但编译器似乎对它很好,并且只调用A::start()
。编辑:一些精度:
A
指针操作C
对象。B::start()
的简单函数,我特别想知道 using 声明是否确实可以“覆盖”虚拟,如果不能,如何允许这两个函数共存。virtual
继承之类的东西。是否有任何方法可以使这项工作,因为我认为它可能有效?
你应该覆盖成员函数并显式调用B::start()
:
class C: public A, private B {
public:
void start() override { B::start(); }
};
为什么编译器会接受此代码有效? 正如我所看到的,现在有两个
start()
函数在C中具有完全相同的签名,但编译器看起来很好并且只调用A::start()
。
你是对的,有两个成员函数可以在C( A::start()
和B::start()
)中访问。 并且在class C
,没有通过using ...::start()
覆盖start()
或使任何基类的start()
可见,当尝试使用unqalified调用成员函数时,将会出现歧义错误来自C
对象的namelookup。
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Error, ambiguous
}
要解决此问题,您必须使用限定名称,例如:
C* c = new C();
c->A::start(); //Ok, calls A::start()
现在,在class C
using B::start()
只需声明start()
以引用B::start()
只要从C
的对象使用此名称即可
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
using B::start();
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Ok, calls B::start()
}
using B::start
使函数void B::start()
在C
可见,它不会覆盖它。 要调用make所有上面的非限定成员函数调用,要调用B::start()
,你应该覆盖C
的成员函数,并使其调用B::start()
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
void start() override { B::start(); }
};
int main(){
A* a = new C();
a->start(); //Ok, calls C::start() which in turn calls B::start()
// ^^^^^^^^^^^^^^^^ - by virtual dispatch
C* c = new C();
c->start(); //Ok, calls C::start() which in turn calls B::start()
}
我想你可能会混淆“公共”和“私人”的含义。 在C ++继承上下文中,这仅仅意味着一切都知道'C'是'A',而对于'B'类型,只有其他'C'对象可以访问'C'对象的父方法('B'方法) 。
第二部分是关于继承歧义。 不 using B::start;
继承确实是模糊的,不会编译(当转到c.start()
),所以实际上在你的例子中添加该语句不是可选的(使用A或B),如果你不想经常使用合格的路径。
我不清楚你是否期望c()->start();
调用'A'方法或'B'方法,但using语句将根据您的需要确定它。 你编写代码的方式有点不确定 - “A” 真的需要开始吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.