用私有基函数覆盖 public 虚函数?
Override public virtual function with private base function?
让我们考虑具有以下接口的两个 classes A
和 B
:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
然后是第三个 class,它继承自两者,A
是公开的,因为它实现了这个 "interface",B
是私有的,因为那是实现细节。
然而,在这个特定的实现中,start()
只需要包含对 B::start()
的调用。所以我想我可以使用快捷方式并执行以下操作:
class C: public A, private B {
public:
using B::start;
};
并完成它,但显然它不起作用。所以我得到 using
private base function doesn't work to override virtuals。由此,有两个问题:
- 有什么方法可以使它像我认为的那样工作吗?
- 为什么编译器会接受此代码有效?正如我所见,现在有两个
start()
函数在 C
中具有完全相同的签名,但编译器似乎没有问题,只调用 A::start()
.
编辑:一些精确度:
- 目标是通过
A
个指针操作C
个对象。
- 我目前正在使用一个只调用
B::start()
的简单函数,我特别想知道 using 声明是否确实可以 "override" 一个虚拟的,如果不能,这是如何允许的两种功能共存。
- 为了简单起见,我可能省略了一些东西,例如
virtual
继承。
Is there any way to make this work as I supposed it may have worked?
您应该覆盖成员函数并显式调用 B::start()
:
class C: public A, private B {
public:
void start() override { B::start(); }
};
Why would the compiler accept this code as valid? As I see it there
are now two start()
functions with the exact same signature in C and
yet the compiler seems fine with it and only calls A::start()
.
你说得对,在 C 中有两个成员函数可以访问(A::start()
和 B::start()
)。在 class C
中,如果不覆盖 start()
或通过执行 using ...::start()
使任何基础 类 的 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 {
};
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()
}
让我们考虑具有以下接口的两个 classes A
和 B
:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
然后是第三个 class,它继承自两者,A
是公开的,因为它实现了这个 "interface",B
是私有的,因为那是实现细节。
然而,在这个特定的实现中,start()
只需要包含对 B::start()
的调用。所以我想我可以使用快捷方式并执行以下操作:
class C: public A, private B {
public:
using B::start;
};
并完成它,但显然它不起作用。所以我得到 using
private base function doesn't work to override virtuals。由此,有两个问题:
- 有什么方法可以使它像我认为的那样工作吗?
- 为什么编译器会接受此代码有效?正如我所见,现在有两个
start()
函数在C
中具有完全相同的签名,但编译器似乎没有问题,只调用A::start()
.
编辑:一些精确度:
- 目标是通过
A
个指针操作C
个对象。 - 我目前正在使用一个只调用
B::start()
的简单函数,我特别想知道 using 声明是否确实可以 "override" 一个虚拟的,如果不能,这是如何允许的两种功能共存。 - 为了简单起见,我可能省略了一些东西,例如
virtual
继承。
Is there any way to make this work as I supposed it may have worked?
您应该覆盖成员函数并显式调用 B::start()
:
class C: public A, private B {
public:
void start() override { B::start(); }
};
Why would the compiler accept this code as valid? As I see it there are now two
start()
functions with the exact same signature in C and yet the compiler seems fine with it and only callsA::start()
.
你说得对,在 C 中有两个成员函数可以访问(A::start()
和 B::start()
)。在 class C
中,如果不覆盖 start()
或通过执行 using ...::start()
使任何基础 类 的 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 {
};
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()
}