C++:使用友元类限制对象实例化

Posted

技术标签:

【中文标题】C++:使用友元类限制对象实例化【英文标题】:C++ : Restricting object instantiation with friend classes 【发布时间】:2013-11-23 14:54:03 【问题描述】:

我有一个类House,它包含一系列类Rooms 作为成员变量。它本身没有任何孩子。

Room 是一个基类,它有几个子类 - Bedroom、Bathroom 等。

我希望能够将房间的创建限制在 House 类中。我有以下内容:

H 文件

class house

public:
    house(/* constructor arguments */);
    ~house(void);
public:
    // generic member variables - length, width, floors, colour, etc.
    room  *room1;
     friend class room;
    friend class bedroom;
    friend class bathroom;

 class room

protected:                 // this compiles as PROTECTED or PUBLIC
    room(/* constructor arguments */);
public:
    virtual ~room(void);
/* generic member variables - length, width, floor, door, etc. */

 class bedroom : public room

public:                    // this compiles as PUBLIC only
    bedroom(/* constructor arguments */);
public:
    ~bedroom(void);
/* specific variables - hasBed, hasWardrobe, etc. */

 class bathroom : public room

protected:                 // this compiles as PUBLIC only
    bathroom(/* constructor arguments */);
public:
    ~bathroom(void);
/* yet more specific variables */

CPP 文件

house::house (/* constructor arguments */)

/* do stuff */

    room = new(nothrow) room(/*agrs*/)      // (1) COMPILES WITH THIS
    room = new(nothrow) bedroom(/*agrs*/)   // (2) COMPILES WITH THIS
    room = new(nothrow) bathroom(/*args*/)  // (3) DOES NOT COMPILE


house::~house(void)  /* clean up + delete */ 

room::room (/* constructor arguments */)
 /* do stuff */ 
room::~room(void)  /* clean up */ 

bedroom::bedroom (/* constructor arguments */): room(/* constructor arguments */)
 /* do stuff */ 
bedroom::~bedroom(void)  /* clean up */ 

bathroom::bathroom(/* constructor arguments */): room(/* constructor arguments */)
 /* do stuff */ 
bathroom::~bathroom(void)  /* clean up */ 

程序在没有受保护的构造函数的情况下成功编译和运行,但是可以从任何地方随意创建房间。一旦我将Room 及其子构造函数切换到 PROTECTED,我就开始出现编译错误(“无法访问”)。如果我交换 Bedroom 和 Bathroom 构造函数的状态,则语句 (2) 将失败并且语句 (3) 在 .CPP 文件中按预期工作。但是,将它们保留为公开意味着它们仍然可以在我不想要的 House 之外创建。

我该如何解决这个问题?创建room 时我依赖多态性,因为在编译时我不知道它会是哪种类型。这是造成问题的原因吗?

【问题讨论】:

【参考方案1】:

C++ 中的友谊是一个利他的概念,而不是一个利己的概念。

一个类可以声明朋友。这并不意味着该类可以访问朋友的受保护成员和私有成员。朋友可以访问声明类的受保护成员和私有成员。

换句话说,友元声明属于授予访问权限的类,而不是希望访问的类。

【讨论】:

漂亮地说,谢谢。我的关系搞错了。【参考方案2】:

您可以使用“朋友”关系:

class Room 
  friend class House;
  // ...

然后,House 将有权访问 Room 的私有(和受保护)成员。这是否真的有用还有待商榷:我很少使用friend,并建议在这种情况下可能没有必要:毕竟,创建房间有什么害处?

【讨论】:

在这个例子中它可能没有必要,因为为了简洁我已经把它去掉了。如果House 最终成为具有自己的子类的基类,那么可能不允许某些派生类创建特定的rooms。

以上是关于C++:使用友元类限制对象实例化的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 运行时如何实例化根元类和其他类描述?

元类,归一化设计,抽象类

YTU 2436: C++ 习题 输出日期时间--友元类

面向对象--元类

python元类深入解析

贰拾叁