繁体   English   中英

用私有基函数覆盖公共虚函数?

[英]Override public virtual function with private base function?

让我们考虑具有以下接口的两个类AB

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM