何时以及为什么要将抽象类声明为朋友类?
我正在尝试阅读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的友元类?
答案 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的实例并且可以访问其私有成员变量。此函数可以在派生类中继承,如果使用派生类实例调用,它将正常工作。
希望这会有所帮助。