C ++将抽象类声明为友元类

时间:2016-01-30 13:41:28

标签: c++

何时以及为什么要将抽象类声明为朋友类?

我正在尝试阅读levelDb

的源代码

它有一个接口(抽象类)DB,它无法访问DB_Impl:

class DB {
 public:
  static Status Open(const Options& options,
                     const std::string& name,
                     DB** dbptr);
  DB() { }
  virtual ~DB();
  virtual Status Put(const WriteOptions& options,
                     const Slice& key,
                     const Slice& value) = 0;
  virtual Status Delete(const WriteOptions& options, const Slice& key) = 0;
  virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0;
  virtual Status Get(const ReadOptions& options,
                     const Slice& key, std::string* value) = 0;
  virtual Iterator* NewIterator(const ReadOptions& options) = 0;
  virtual const Snapshot* GetSnapshot() = 0;
  virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
  virtual void GetApproximateSizes(const Range* range, int n,
                                   uint64_t* sizes) = 0;
  virtual void CompactRange(const Slice* begin, const Slice* end) = 0;
 private:
  // No copying allowed
  DB(const DB&);
  void operator=(const DB&);
};

和实现DB_Impl。

在db_impl.h中:

class DBImpl : public DB {
  public:
    ... // implementation of the DB interface
  private:
    friend class DB;
    ... // internal methods and variables
}

为什么将抽象类DB声明为DBImpl的友元类?

2 个答案:

答案 0 :(得分:0)

抽象类可以具有(通常具有)非抽象部分,例如普通成员函数。

在您的示例中,DB可能有一些正常的成员函数f() { /* ... */ }。此外,类设计可以使DB知道某些派生类。这经常(但并非总是)是阶级设计破碎的标志。所以f实际上可能需要一个DBImpl参数,需要访问它的一些私有成员。在这种情况下,friend可以达到预期的效果。

这是一个完整的例子:

class DBImpl;

class DB {
public:
    virtual ~DB() {}

    void f(DBImpl& db_impl); // DB is aware of a derived class

private:
    virtual void virtual_function() = 0; // just to make the class abstract
};

class DBImpl : public DB {
private:
    void virtual_function() override {} // just to make the class concrete
    void g() {} // DBImpl wants only DB to be able to call this

    friend class DB;
};

void DB::f(DBImpl& db_impl) {
    db_impl.g(); // DB can call DBImpl's private member function
}

答案 1 :(得分:0)

可能是静态函数DB ::在DB类中打开使用DBImpl私有/受保护成员变量/函数。

此外,如果您没有在此处显示完整的DB类声明并且它有额外的代码,请检查是否存在DB类的非纯虚函数,它可能具有DBImpl的实例并且可以访问其私有成员变量。此函数可以在派生类中继承,如果使用派生类实例调用,它将正常工作。

希望这会有所帮助。