虽然我已经看到final
并且虚拟继承方法实现了这一点,但我无法理解为什么定义除了默认的私有构造函数之外没有构造函数阻止类继承。 (此外,基类的复制构造函数和复制赋值方法应作为预防措施声明为私有。)
基本上我的意思是,如果基类的构造函数是私有的,并且它没有其他构造函数,那么,当派生类想要扩展此基类时:
派生类无法调用基类的默认构造函数,因为它是私有的
派生类不能调用基类的任何非默认构造函数,因为没有这样的构造函数
所以这是一个编译时错误,我找不到另一种方法来克服这个问题。
我确信我错了;否则,我可以在互联网上找到一个页面,提供这个作为一种使类不可继承的方式,但请向我解释为什么我错了。
答案 0 :(得分:2)
final
和私有构造函数不是一回事。
考虑一下:
struct A final {};
struct B: A {};
int main() {}
它不会编译,这是事实 现在考虑一下:
class A { A() {} };
struct B: A {};
int main() {}
它编译。好的,发生了B()
构造函数被删除但你没有使用它。如果您将定义略微更改为:
struct B: A { B(): A() {} };
无论如何,上一个例子只是工作(对于工作的某些意思),那有什么区别?
final
禁止继承。私有构造函数不允许您构造 类型的对象,但您仍然可以定义 类型。因此,你可以做这样的事情(这没有多大意义,但给你一个想法):
#include<type_traits>
class A { A() {}};
struct B: A {};
template<typename T>
void f() {
static_assert(std::is_base_of<A, B>::value, "!");
// ...
}
int main() {
f<B>();
}
如果你不能继承A
,它是如何编译的?因为您的假设是错误的,所以您可以继承A
。您不能构造B
类型的对象,但只要不尝试创建实例,您仍然可以使用B
作为类型。另一方面,如果你把final
放在那里就会出现编译时错误,那就完全不行了,你不能以任何方式使用B
类型。
答案 1 :(得分:0)
为什么标准禁止这样做?从理论上讲,没有什么能阻止你将Derived类声明为Base类的朋友。这将确保扩展基类的唯一可能方法是通过众所周知的类。我无法想到任何实际案例,我认为这很糟糕,但这样做恐怖是可能的......
struct BaseClass
{
friend struct DerivedClass;
private:
BaseClass() {}
};
struct DerivedClass : BaseClass
{
public:
DerivedClass() {}
};