![](/img/trans.png)
[英]Is there a way to prevent a public function being used from another class without using Friend classes (C++)
[英]Is there a way, using templates, to prevent a class from being derivable in C++
我需要阻止一个类派生,所以我想,这是Boost必须已经完成的事情。 我知道他们有一个不可复制的,他们必须有一个不可复制的......
想象一下,当我找不到它时,我感到惊讶......
这让我思考..必须有一个理由。 也许不可能使用模板..
我确定它是否很容易在升级库中。
我知道如何在不使用模板的情况下完成它,即使用带有私有构造函数的基类,即
class ThatCantBeDerived; // Forward reference
class _NonDeriv
{
_NonDeriv() {}
friend class ThatCantBeDerived;
};
class ThatCantBeDerived : virtual public _NonDeriv
{
public:
ThatCantBeDerived() :
_NonDeriv()
{
}
};
或类似的东西..
也许它是导致问题的前向参考,或者可能没有可移植的方法来实现它。
无论哪种方式,我不确定为什么它不是在提升..
有任何想法吗?
在C ++中无法阻止派生 - 你无法阻止这种情况:
class A {};
class B : public A {};
但是,有几种方法可以防止B类对象的实例化 。这是值得的,值得商榷。 我更愿意记录A类不用于派生,并给它一个非虚拟析构函数。
另请注意,名称_NonDeriv在C ++中保留用于实现,所有名称都以下划线和大写字母开头。 您不能在自己的代码中创建此类名称。
根据当前规范,明确禁止“朋友”模板参数,因此模板化您的示例将使其不符合标准。 Boost可能不希望在其库中添加类似的东西。 我相信这个限制在Ox中正在放松,并且编译器有一些变通方法。
Adobe使用模板有一个不完美的解决方案。
问题在于,由于模板不能声明依赖于参数的朋友[*],它依赖于受保护的构造函数而不是私有。 这是一个部分解决方案,当有人错误地决定从您的类派生时它会触发编译器错误,但它不是一个完整的解决方案,因为有人故意强制继承。
template <typename SealedClass>
class seal
{
protected:
seal() {}
};
class Sealed : private virtual seal<Sealed>
{
//...
};
class NaiveExtension : public Sealed { // fails
NaiveExtension() {} // NaiveExtension cannot call seal<Sealed> constructor
};
class BreakingExtension : public Sealed, private virtual seal<Sealed> {
BreakingExtension() : seal<Sealed>(), Sealed() {} // now it can
};
优点是它可以被模板化(adobe库实际上定义了一个宏,它将隐藏来自随意读者的'私有虚拟')。 缺点是它可以被打破。
然后,您可以随时执行C ++ FAQ建议的关于阻止某些功能的一些问题:
“我怎么能禁止人们......”: 写下评论不要这样做
“但我怎么能真正地抑制别人......”: 写一条评论:如果......你将被解雇
“但是,如果他们不遵循评论,我该如何实际阻止它?”: 解雇他们
[*]只要有可用,只要在编译器中实现,这个限制就会被即将推出的标准带走......
简单:
使所有构造函数都是私有的:
然后,nobdy可以从你那里衍生出来。 当然,这会增加一些问题,比如你不能实例化对象的变量,但是有使用公共静态成员方法和朋友的变通方法:
#include <memory>
class InstnaceCantDeriveFromMe;
class CantDeriveFromMe
{
private:
friend class InstnaceCantDeriveFromMe;
CantDeriveFromMe()
{}
public:
static std::auto_ptr<CantDeriveFromMe> getDynamicObj()
{
return std::auto_ptr<CantDeriveFromMe>(new CantDeriveFromMe());
}
};
class Plop: public CantDeriveFromMe
{
};
class InstnaceCantDeriveFromMe
{
private:
CantDeriveFromMe instnace;
public:
CantDeriveFromMe& get() {return instnace;}
};
int main()
{
std::auto_ptr<CantDeriveFromMe> a = CantDeriveFromMe::getDynamicObj();
InstnaceCantDeriveFromMe b;
// This fails to compile:
Plop c;
}
也许可以使用CRTP将您的示例转换为模板 - 这是一种奇怪的重复模板模式:
template <typename T>
_NonDeriv
{
_NonDeriv() {}
friend class T;
};
class ThatCantBeDerived : virtual public _NonDeriv<ThatCantBeDerived>
{
public:
ThatCantBeDerived() :
_NonDeriv()
{
}
};
可能会工作......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.