禁止在C ++中访问基类句柄

时间:2015-01-13 16:26:36

标签: c++

我正在编写一个C ++库,我想隐藏基类的名称,即我不希望用户能够使用基类指针(或引用)来引用派生类。 / p>

假设我有一个班级

class Message
{
  public:
  //...
};

和两个派生类:

class SpecialMessage : public Message
{
  //..
};

class NeatMessage : public Message
{
  //..
};

如何使用户无法执行以下操作:

SpecialMessage specialMessage{};
Message* baseHandle = &specialMessage;

我想排除这种行为的一个原因是我不想声明Message的析构函数是虚拟的。

我想过将Message隐藏在详细的命名空间中:

namespace detail
{
    class Message
    {
    };
}

但这有点奇怪,如果有这么倾向,用户仍然可以访问Message类。

编辑:

私有继承对我不起作用,因为我仍然希望用户能够访问Message的方法(通过派生类的对象)。组合也不会 - 因为为了使用户可以访问Message的方法,我必须在派生类中编写包装器代码。

声明基类的析构函数是受保护的(正如Sebastian Redl所建议的那样)虽然是一个有趣的想法,但也不适合我,因为它仍然允许用户获得基类句柄。

4 个答案:

答案 0 :(得分:3)

您可以私下继承,也可以在Message内嵌入SpecialMessage对象,而不是派生。

或者,如果您从未真正需要原始Message个对象,则可以使Message析构函数受到保护。

答案 1 :(得分:2)

使用受保护或私有继承而不是公共:

class SpecialMessage : private Message {};

或者,为了解决您没有虚拟析构函数的真正问题,只需使Message的析构函数受到保护即可。然后,即使它们可以创建基类指针,它们也不能通过它非多态地破坏对象。

我必须要求您考虑您的设计:为什么您想要一个Message界面?如果基类完全是非多态的,那么绝对应该使用组合或私有继承而不是公共继承。公共继承仅用于替换,而不是实现。

答案 2 :(得分:0)

偏好composition over inheritance。如果你继承自Message,我无法想到从用户那里隐藏它​​的声明。当然你可以像你建议的那样模糊它,但声明必须在那里 - 期间。

如果您使用Message作为私人成员但未发送图书馆的源代码,则用户将看不到该声明。要让您的用户能够访问Message的功能,请使用facade pattern.

答案 3 :(得分:0)

可能有更好的方法来提供您使用不同架构所需的语义。但是,要解决此问题,您可以随时执行一些粗略的模板魔术:

#include <iostream>

class Message
{
public:
    void Foo() {}
    int Bar(int i) {return i + 10;}
};

class SpecialMessage
{
private:
    Message message;
public:
    template<typename T, typename... Args>
    auto MessageCall(T t, Args... args) -> decltype((message.*t)(args...))
    {
        return (message.*t)(args...);
    }
};

int main()
{
    SpecialMessage m;
    m.MessageCall(&Message::Foo);
    std::cout << "\n test: " << m.MessageCall(&Message::Bar, 10);
    return 0;
}

有点脏,是的......

相关问题