继承时如何避免创建基类的副本?C++



我有一个"数据库";类,该类具有存储用户的映射。还有一个";Auth";从"继承的类;数据库";并获取用户地图以便在授权期间找到正确的用户。还有";管理员";类,它也继承自";数据库";并且可以添加新用户。但问题是,当继承";Auth";以及";管理员";从";数据库";,两个";数据库";创建。因此,如果";管理员";添加一个新用户;Auth";不会知道;数据库"?

class User;
class Database
{
private:
map<int, User> users;
protected:
Database() {}
void readFileOfUsers();
auto& getUsers() { return users; }
};
class Auth : public Database
{
private:
int userID;
public:
Admin itsAdmin;
User* itsUser;
Auth() : userID(0) { readFileOfUsers(); }
void logIn(std::string login, std::string password);
};
class Admin : public Database
{
public:
void getDatabase() { readFileOfUsers(); }// ?
void addNewUser(std::string login, std::string password); 
};
class User
{
private:
std::string login;
std::string password;
public:
void userActions();
};

问题:

Auth和Admin需要访问数据库成员,但不应该创建数据库的新实例。

解决方案:

如果没有Minimal Reproductible Example,很难提供帮助,但从中可以看出,您可能应该使用友元类而不是继承,并通过引用将数据库传递给类。

类似这样的东西:

class Database
{
//...
Database() {}
friend class Auth;
friend class Admin;
};
class Auth
{
//...
void logIn(Database&, std::string login, std::string password);
};
class Admin
{
//...
void addNewUser(Database&, std::string login, std::string password);
};

然后是这样的:

//...
Database db;
Admin someone;
someone.addNewUser(db,"someUser","somePassword");
//...

正如注释所指出的,AdminAuth本身并不是数据库。我不完全确定你在做什么,但一个合理的模型是:

CCD_ 3(保持或保持对所有数据的访问(。Database还有一个成员变量,用于标识所有用户。然后是一个Session类,该类将经过身份验证的用户标识为已连接到数据库。它将有一个指向Database的指针(或甚至引用(和一个指向User的指针。

如果您想表示Database只能通过会话访问(除了一些创建Database的引导程序外,请使用friend.

但是要小心friend是非常强大的。另一个称为SessionChannel的类可以是friend,并且用于限制对Database的访问,并且其本身具有"作为朋友的会话"。它甚至不需要任何成员变量。

最佳实践是使用组合而不是继承。只在严格需要多态性的地方使用它,因为代码行必须在类型之间动态切换。对于templates,您应该会发现这种情况相对罕见。

继承,特别是OO和C++有一个坏名声,因为继承被过度使用,而当这种情况发生时,实际上会导致人们最初声称的OO缺乏灵活性。

不要相信任何人说C++是关于继承和多态性的。令人遗憾的是,它仍然是这样被教导的,尽管它已经有大约十年甚至更长的时间没有实现了。

如果要对"真实"数据库建模,可以创建一个DatabaseServer对象,该对象包含一组数据库和一组用户,这些用户可能被授予对零个或多个数据库的访问权限,然后在每个数据库中进行授权。

最新更新