有没有办法C++将给定类的功能限制为仅另一个类(不使用继承,朋友)?

Is there a way in C++ to restrict a function of a given class to another class only(without using inheritance, friend)?

本文关键字:另一个 继承 朋友 C++ 有没有 功能      更新时间:2023-10-16

我想设计一个具有函数的类,该函数应限制为仅从另一个类调用。具体来说,在给定的代码中

class Club
{
int id;
string name;
vector<string> members;
int generateId() 
{ 
static int i=1;
return i++;
}
public:
Club(string name) { this->name = name; this->id = generateId(); }  
void registerMember(string memberName) { members.push_back(memberName); }
int getId() { return id; }
};
class Application
{
vector<Club> clubs;
public:
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
}
};

用户(公共用户(可以创建类Club的对象,并使用函数registerMember()注册,因为它是公共的。我希望用户通过类Application的对象注册,仅使用addMemberToClub()函数。如果用户按照前面提到的方式进行,我无法跟踪用户。有没有办法强制执行后者?

  1. 我不想使用访问修饰符protected因为继承在这里没有意义。
  2. 我不想使用friend关键字,因为它被认为是不好的做法。

这是一种"锁和密钥"方法,允许另一个类(并且仅该类(甚至另一个类中的单个函数仅访问一个成员函数,这与同时公开所有私有成员的friend不同:

#include <iostream>
class Key;
class Locked
{
static const char* const Greeting;
public:
static Key secretive();
static void attacker();
};
struct Admin
{
void doit();
};
class Key
{
~Key() = default;
//friend class Admin;
friend void Admin::doit();
friend Key Locked::secretive();
};
void Admin::doit()
{
Locked::secretive();
std::cout << Locked::Greeting; // compile error
}
constexpr const char* Locked::Greeting = "Hello!n";
Key Locked::secretive()
{
std::cout << Greeting;
return Key();
}
void Locked::attacker()
{
std::cout << Locked::Greeting; // ok, it's just private
Locked::secretive(); // compile error, it's locked down tight
}
int main()
{
Admin a;
a.doit();
std::cout << Locked::Greeting; // compile error
Locked::secretive(); // compile error
}

它还解决了"首先声明哪个类?"的问题,该问题阻止两个类相互连接彼此的各个成员函数,因为受限操作只需要遵循键类型的前向声明;其他类型的完整定义可以(并且在此示例中确实(出现在键定义上方, 允许在密钥类型的 FRIEND 指令中命名单个成员。

请注意,在此解决方案中,同一类的其他成员可以访问锁定函数的"明显"事实并非如此。 编译器阻止Locked::attacker()调用Locked::secretive()

另请注意,我在此示例中使用了static来最大程度地减少必须创建的对象数量,但该方法也适用于非静态成员函数。


限制程序的哪个部分可以调用受保护函数的一种可能更简单的方法是使用一个简单的标志:

class Application
{
static bool addingMember = 0;
public:
static bool isRegistrationOk() { return addingMember; }
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
addingMember = true;
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
addingMember = false;
}
};
void Club::registerMember(string memberName)
{
assert(Application::isRegistrationOk());
members.push_back(memberName);
}

更容易摸索,但这是一个运行时检查而不是编译时检查,并且需要额外的工作才能使线程安全。 但它在不使用friend或继承的情况下实现了目标。

friend是在这种情况下使用的合适机制。在ClubregisterMember保密,Club可以赋予Application友谊:

class Club
{
// ...
void registerMember(string memberName) { members.push_back(memberName); }
public:
// ...
friend class Application;
};

现在只有Application可以打电话给registerMember,当然还有Club

这是一个演示。

相关文章: