C++ 通过定义默认私有构造函数使类不可继承

C++ 通过定义默认私有构造函数使类不可继承,c++,C++,尽管我已经看到了final和虚拟继承方法实现了这一点,但我无法理解为什么定义任何构造函数(除了默认的私有构造函数)都不能阻止类被继承。(此外,作为预防措施,基类的复制构造函数和复制赋值方法应声明为私有。) 基本上我的意思是,如果基类的构造函数是私有的,并且没有其他构造函数,那么,当派生类想要扩展这个基类时: 派生类无法调用基类的默认构造函数,因为它是私有的 派生类无法调用基类的任何非默认构造函数,因为没有此类构造函数 所以这是一个编译时错误,我找不到其他方法来克服它 我肯定我在某个地方错了;否则

尽管我已经看到了
final
和虚拟继承方法实现了这一点,但我无法理解为什么定义任何构造函数(除了默认的私有构造函数)都不能阻止类被继承。(此外,作为预防措施,基类的复制构造函数和复制赋值方法应声明为私有。)

基本上我的意思是,如果基类的构造函数是私有的,并且没有其他构造函数,那么,当派生类想要扩展这个基类时:

  • 派生类无法调用基类的默认构造函数,因为它是私有的

  • 派生类无法调用基类的任何非默认构造函数,因为没有此类构造函数

  • 所以这是一个编译时错误,我找不到其他方法来克服它


    我肯定我在某个地方错了;否则,我可以在互联网上找到一个页面,提供这种方式使类不可继承,但请向我解释为什么我错了。

    为什么标准会禁止这样做?理论上,没有什么可以阻止您将派生类声明为基类的朋友。这将确保扩展基类的唯一可能方法是通过非常知名的类。我想不出任何实际的例子,我认为这是不好的,但有可能做这样的恐怖

    struct BaseClass
    {
    friend struct DerivedClass;
    
    private:
        BaseClass() {}
    };
    
    struct DerivedClass : BaseClass
    {
    public:
        DerivedClass() {}
    };
    

    final
    和私有构造函数不是一回事

    考虑这一点:

    struct A final {};
    struct B: A {};
    
    int main() {}
    
    class A { A() {} };
    struct B: A {};
    
    int main() {}
    
    它无法编译,这是事实。
    现在考虑这个问题:

    struct A final {};
    struct B: A {};
    
    int main() {}
    
    class A { A() {} };
    struct B: A {};
    
    int main() {}
    
    它编译。好的,碰巧
    B()
    构造函数被删除了,但您没有使用它。如果将定义稍微更改为:

    struct B: A { B(): A() {} };
    
    不管怎样,前面的示例只适用于某些平均值,那么有什么区别呢?
    final
    禁止继承。私有构造函数不允许您构造该类型的对象,但您仍然可以定义该类型。因此,您可以这样做(这没有多大意义,但给了您一个想法):

    #包括
    类A{A(){};
    结构B:A{};
    模板
    void f(){
    静态断言(std::是::value,“!”)的基础;
    // ...
    }
    int main(){
    f();
    }
    

    如果您不能从
    A
    继承,它是如何编译的?因为您的假设是错误的,所以您可以从
    A
    继承。您不能构造类型为
    B
    的对象,但只要不尝试创建实例,您仍然可以将
    B
    用作类型。另一方面,如果你把
    final
    放在那里,你会得到一个编译时错误,仅此而已,你不能以任何方式使用type
    B

    你也可以使用你的方法。如果你深入研究,你可能会发现这两种方法是如何不同的,以及何时应该使用一种方法与另一种方法。你想知道这是否有效,或者为什么有效,或者如何绕过它吗?@R Sahu你能解释一下区别,或者提供我可以阅读搜索的链接相关关键词吗?@meagar事实上,我甚至没有尝试过我提到的方法,但我想知道的是,这是否有效,如果有效,为什么不在文献中提到将类作为不可继承的方式?@mualloc,因为我们现在有了
    final
    ?是的,当然可以使用私有构造函数,但是为什么呢?既然
    final
    已经存在,这是错误的解决方案。你可以用扳手敲入钉子,但你不应该奇怪为什么“文献”在锤子存在的时候不提及这个事实。类a的构造函数是公共的,所以这不是我要说的。@mualloc类的默认可见性是
    private
    ,因此
    类C{C(){}
    相当于
    类C{private:C(){}。构造函数实际上不是公共的。如果在第二个示例中尝试构造a
    B
    ,它将无法编译。好的,关于默认可见性问题,您是对的,谢谢您的解释。这就是我一直在寻找的。顺便说一句,我很抱歉这么粗心,因为我没有编译我描述的代码以便更好地发现和定义问题。实际上,结构B:A{}和结构B:A{B():A(){}之间有什么区别?