更简单的“防止派生类”在 C++
假设存在阻止从某个类派生的合理理由,Bjarne 在此处 获取“我可以阻止人们从我的班级派生吗?”的答案
然而,我想到:
class final {
protected:
final() { } // line 3
};
class B : private virtual final {
};
class D : public B { // line 9
};
int main() {
B b;
D d; // line 14
}
当尝试编译时,人们会得到:
foo.cpp: In constructor ‘D::D()’:
foo.cpp:3: error: ‘final::final()’ is protected
foo.cpp:9: error: within this context
foo.cpp: In function ‘int main()’:
foo.cpp:14: note: synthesized method ‘D::D()’ first required here
我的解决方案适用于所有情况吗?恕我直言,它更好,因为类 final
是通用的,不需要预先了解该类来防止派生。
Going under the assumption that there is a legitimate reason for preventing derivation from some class, Bjarne gives a solution here for the answer to "Can I stop people deriving from my class?"
However, I thought of:
class final {
protected:
final() { } // line 3
};
class B : private virtual final {
};
class D : public B { // line 9
};
int main() {
B b;
D d; // line 14
}
When trying to compile, one gets:
foo.cpp: In constructor ‘D::D()’:
foo.cpp:3: error: ‘final::final()’ is protected
foo.cpp:9: error: within this context
foo.cpp: In function ‘int main()’:
foo.cpp:14: note: synthesized method ‘D::D()’ first required here
Does my solution work for all cases? IMHO, it's better because the class final
is generic and doesn't require foreknowledge of the class to prevent derivation from.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该解决方案相当糟糕,可以使用 CRTP 对其进行改进(adobe 就是这样做的),但它不会是一个完整的解决方案。您的代码的问题在于,另一个不想破坏您的合同(她是一个好人)但不知道她不应该从您的类派生的程序员可能想要锁定其他人从她自己的类派生:
请注意连恶意都没有,契约就毁了。 CRTP 的改进是:
这将捕获之前的错误,因为她的代码将是:
由于她不是从
seal继承,编译器将捕获它。
这种方法的问题在于,它不会阻止某些顽固(或恶意)的程序员编写:
成为密封类的子级,并因此获得对您自己的类的访问权限。
在 C++0x 中,我相信(必须重新检查)他们会提出模板不能与模板参数交友的限制,这将是迈向通用类型安全解决方案的良好一步。 class sealer:
这种方法的优点(目前不可用)是因为构造函数和析构函数是私有的,只有朋友才能实例化该类型。因为您使用 CRTP 从特定实例继承,并将您自己的类型作为参数传递,所以您告诉编译器只有您可以实际实例化您的基类,并且所有部分都就位。
The solution is rather bad, it could be improved with CRTP (adobe does so) but it won't be a complete solution. The problem with your code is that another programmer that does not want to break your contract (she is a good person) but does not know that she should not derive from your class might want to lock others from deriving from her own class:
Note that there is not even malign intention, and the contract is broken. The improvement with CRTP would be:
This will catch the previous mistake, as her code would be:
And as she is not inheriting from
seal<YourSealedClass>
the compiler will catch it up.The problem with this approach is that it does not block some stubborn (or malign) programmer from writing:
To become a child of the sealing class, and as such gain access to your own class.
In C++0x I believe (would have to recheck it) that they will raise the restriction that a template cannot befriend a template argument, and that will be a good step into a generic typesafe solution for a class sealer:
The advantage of this approach (currently unavailable) is that because the constructor and destructors are private only friends can instantiate the type. Because you are using the CRTP to inherit from an specific instantiation passing your own type as argument, you are telling the compiler that only you can actually instantiate your base, and all pieces fall right into place.
尝试:
Try: