【问题标题】:Whats the usage of private virtual methods? [duplicate]私有虚拟方法的用途是什么? [复制]
【发布时间】:2020-09-07 10:37:33
【问题描述】:

考虑下面的例子

#include <iostream>
#include <string>

class A
{
public:
    virtual void foo() { std::cout<< "FOO A\n"; }

private:
    void bar() { std::cout<< "BAR A\n"; }
    virtual void vbar() { std::cout<< "VBAR A\n"; }
};

class B : public A
{
public:
    void foo() { std::cout<< "FOO B\n"; bar(); vbar(); }
private:
    void bar() { std::cout<< "BAR B\n"; }
    virtual void vbar() { std::cout<< "VBAR B\n"; }
};

int main()
{
    A* b = new B();
    b->foo();
}

输出会给我们

FOO B
BAR B
VBAR B

由于我首先想到了它的简单示例,因此我无法弄清楚任何私有虚拟方法用例。在公共虚拟方法的情况下,基指针类接口将适应其定义的 vtable,但就像给定的私有虚拟示例一样,这无关紧要

【问题讨论】:

标签: c++ virtual-functions


【解决方案1】:

有些情况下它可能有用,一些人认为,如果可能,它应该是首选方法,例如 Herb Sutter:

准则 #2:最好将虚拟函数设为私有。

...这使派生类可以覆盖函数以根据需要自定义行为,而无需通过使派生类可调用虚函数来进一步直接公开虚函数(如果函数只是受保护的话,这是可能的)。关键是虚拟功能的存在允许定制;除非还需要从派生类的代码中直接调用它们,否则除了私有之外,没有必要将它们设为任何东西。但有时我们确实需要调用虚函数的基本版本(参见文章“Virtually Yours”[5] 作为示例),在这种情况下,只有保护这些虚函数才有意义,因此:

准则#3:仅当派生类需要调用虚函数的基实现时,才使虚函数受保护...

http://www.gotw.ca/publications/mill18.htm

【讨论】:

    【解决方案2】:

    一种可能的用途是让基类定义一个结构,并让派生类实现所述结构的组件的行为(template method pattern)。例如,

    struct foo
    {
        void do_stuff() {
            // defines order in which some operations are executed
            do_op1();
            do_op1();
            do_op3();
        }
    private:
         // These don't have to be pure virtual. A base,
         // default implementation could also be provided.
        virtual void do_op1() = 0;
        virtual void do_op2() = 0;
        virtual void do_op3() = 0;
    };
    
    // implements the operations
    struct foo1 : foo
    {
    private:
        void do_op1() override { ... }
        void do_op2() override { ... }
        void do_op3() override { ... }
    };
    

    虚方法是私有的,因为单独调用它们没有意义。基类知道何时以及如何调用它们。

    在“现代 C++”中可能有更简单更好的实现方式,但这种事情在 90 年代和 00 年代可能已经看到了。

    【讨论】:

      猜你喜欢
      • 2012-04-09
      • 2020-05-14
      • 1970-01-01
      • 2013-12-03
      • 2020-02-11
      • 1970-01-01
      • 2011-02-08
      • 2012-09-23
      • 1970-01-01
      相关资源
      最近更新 更多