我需要阻止一个类派生,所以我想,这是Boost必须已经完成的事情。我知道他们有不可复制的,他们必须有一个不可复制的......
想象一下,当我找不到它时,我感到惊讶......
这让我思考..必须有一个理由。也许不可能使用模板..
我确定它是否很容易在升级库中。
我知道如何不使用模板,即使用带有私有构造函数的基类,即
class ThatCantBeDerived; // Forward reference
class _NonDeriv
{
_NonDeriv() {}
friend class ThatCantBeDerived;
};
class ThatCantBeDerived : virtual public _NonDeriv
{
public:
ThatCantBeDerived() :
_NonDeriv()
{
}
};
或者像这样......
也许这是导致问题的前向引用,或者可能没有可行的方法来实现它..
无论哪种方式,我都不确定为什么它没有加强..
有什么想法吗?
答案 0 :(得分:7)
答案 1 :(得分:3)
C ++中无法阻止派生 - 你无法阻止这种情况:
class A {};
class B : public A {};
但是,有几种方法可以阻止类型B对象的实例化。这是值得的麻烦是值得商榷的。我更愿意记录A类不是为了派生,而是给它一个非虚拟析构函数。
另请注意,C ++中保留名称 _NonDeriv 用于实现,所有名称都以下划线和大写字母开头。您不能在自己的代码中创建此类名称。
答案 2 :(得分:2)
根据当前规范,明确禁止“朋友”模板参数,因此模板化您的示例会使其不符合标准。 Boost可能不希望在其库中添加类似的东西。我相信这个限制在Ox中正在放松,并且编译器也有解决方法。
答案 3 :(得分:1)
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建议:
'如何禁止人们......':写评论不要这样做
'但是我如何才能真正抑制其他人...':写一条评论:如果......你会被解雇
'但如果他们不遵循评论,我该如何实际阻止?':解雇他们
[*]只要有可用,只要在编译器中实现,这个限制就会被即将推出的标准带走......
答案 4 :(得分:1)
易:
将所有构造函数设为私有:
然后,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;
}
答案 5 :(得分:0)
也许可以使用CRTP将您的示例转换为模板 - 这是一种奇怪的重复模板模式:
template <typename T>
_NonDeriv
{
_NonDeriv() {}
friend class T;
};
class ThatCantBeDerived : virtual public _NonDeriv<ThatCantBeDerived>
{
public:
ThatCantBeDerived() :
_NonDeriv()
{
}
};
可能会工作......