【问题标题】:virtual function in private or protected inheritance私有或受保护继承中的虚函数
【发布时间】:2010-01-28 20:51:58
【问题描述】:

公共继承中的虚函数很容易理解。那么私有或受保护继承中的虚函数有什么意义呢?

例如:

class Base {
public:
virtual void f() { cout<<"Base::f()"<<endl;}
};

class Derived: private Base {
public: 

void f() { cout<<"Derived::f()"<<endl;}

};

这还叫覆盖吗?这个案子有什么用?这两个f()是什么关系?

谢谢!

【问题讨论】:

  • 接受的答案并没有真正解决这个问题,我有同样的问题 - 而不是问一个新的问题,我正在解决这个问题。

标签: c++


【解决方案1】:

私有继承只是一种实现技术,而不是一种 is-a 关系,正如 Scott Meyers 在 Effective C++ 中解释的那样:

class Timer {
public:
    explicit Timer(int tickFrequency);
    virtual void onTick() const; // automatically called for each tick
    ...
};

class Widget: private Timer {
private:
    virtual void onTick() const; // look at Widget private data
    ...
};

Widget 客户端不应该能够在 Widget 上调用 onTick,因为这不是 Widget 概念接口的一部分。

【讨论】:

  • 事实上,这只是一个很好的例子。我回答错了问题。哎呀。 :-)
【解决方案2】:

您的f() 方法仍被覆盖。这种关系在实现Template Method 设计模式时很有用。基本上,您将在基类中实现通用的操作集。然后,这些基类操作将调用一个虚拟方法,例如您的f()。如果派生类覆盖f(),则基类操作最终会调用f() 的派生版本。这允许派生类保持基本算法相同,但改变行为以满足它们的需要。这是一个简单的例子:

#include <iostream>

using namespace std;

class Base
{
public:
  virtual void f() { cout<<"Base::f()" << endl; }
protected:
  void base_foo() { f(); }
};

class DerivedOne: private Base
{
public: 
  void f() { cout << "Derived::f()" << endl;}
  void foo() { base_foo(); }
};

class DerivedTwo: private Base
{
public: 
  void foo() { base_foo(); }
};

int main()
{
  DerivedOne d1;
  d1.foo();

  DerivedTwo d2;
  d2.foo();
}

这是运行时的结果:

$ ./a.out 
Derived::f()
Base::f()

两个派生类调用相同的基类操作,但每个派生类的行为不同。

【讨论】:

    【解决方案3】:
    • 不需要为不同功能的每个组合都设置一个点。您可以简单地组合它们。
    • 派生类可以访问虚拟受保护成员,因此对派生类很有用。
    • 虚拟私有成员可供朋友类访问,因此对他们很有用。

    【讨论】:

      【解决方案4】:

      私有继承和受保护继承都允许覆盖私有/受保护基类中的虚函数,并且都不声称派生是其基类的一种。

      受保护的继承允许派生类的派生类知道继承关系并仍然覆盖虚函数。

      Derived 类中的Base 类私有继承会破坏派生类和基类之间的所有概念联系。派生类只是根据基类实现的,仅此而已。私有继承只是一种实现技术,并不意味着所涉及的类之间存在任何关系。

      【讨论】:

        【解决方案5】:

        一个例子是:

        /// Thread body interface
        class runnable
        {
        public:
        
            virtual ~runnable() {}
            virtual void run() =0;
        };
        
        /// Starts OS thread, calls p->run() in new thread
        thread_id start_thread( runnable* p );
        
        /// Has a private thread
        class actor: private runnable, private noncopyable
        {
        private:
        
            thread_id tid; /// private thread
        
        public:
        
            actor() { tid = start_thread( this ); } // here this IS-A runnable
            // ...
            virtual ~actor() { stop_thread( tid ); }
        
        private:
        
            virtual void run() { /* work */ }
        };
        

        【讨论】:

        • 但是它怎么称呼run?这是私人的。
        • 哦,开枪!谢谢。需要更多的咖啡。我打算使用 public run() 和 virtual private do_run()。更正。
        • 8 年后……还在喝咖啡吗?哈哈。另外既然这是私有继承,你能不能有一个基类指针,指向一个子类的对象?
        猜你喜欢
        • 2019-08-24
        • 1970-01-01
        • 2023-03-03
        • 1970-01-01
        • 2010-10-26
        • 2013-12-14
        相关资源
        最近更新 更多