如果在C+;中向基类添加了虚拟或非虚拟函数,是否必须重新编译整个类层次结构+;? 我试图了解C++中一个类的VTHO是多么敏感,为此,我需要知道下面的3个变化场景是否需要重新编译整个类层次结构(总共3个头文件)。首先,这里是我的类层次结构: class A { public: virtual void method1() = 0; virtual void method2() = 0; virtual ~A() {} }; class B : public A { public: virtual void method1() {}; virtual void method2() {}; virtual ~B() {} }; class C : public A { public: virtual void method1() {}; virtual void method2() {}; virtual ~C() {} };

如果在C+;中向基类添加了虚拟或非虚拟函数,是否必须重新编译整个类层次结构+;? 我试图了解C++中一个类的VTHO是多么敏感,为此,我需要知道下面的3个变化场景是否需要重新编译整个类层次结构(总共3个头文件)。首先,这里是我的类层次结构: class A { public: virtual void method1() = 0; virtual void method2() = 0; virtual ~A() {} }; class B : public A { public: virtual void method1() {}; virtual void method2() {}; virtual ~B() {} }; class C : public A { public: virtual void method1() {}; virtual void method2() {}; virtual ~C() {} };,c++,c++11,virtual-functions,vtable,C++,C++11,Virtual Functions,Vtable,以下是我的设想: 将非虚拟方法添加到基类A中: void method3() {}; virtual void method3() {}; virtual void method3() = 0; 将具有主体的虚拟方法添加到基类A: void method3() {}; virtual void method3() {}; virtual void method3() = 0; 将纯虚拟方法添加到基类A中: void method3() {}; virtual void meth

以下是我的设想:

  • 将非虚拟方法添加到基类A中:

    void method3() {};
    
    virtual void method3() {};
    
    virtual void method3() = 0;
    
  • 将具有主体的虚拟方法添加到基类A:

    void method3() {};
    
    virtual void method3() {};
    
    virtual void method3() = 0;
    
  • 将纯虚拟方法添加到基类A中:

    void method3() {};
    
    virtual void method3() {};
    
    virtual void method3() = 0;
    
  • 在场景1中,未对vtable进行任何更改。B和C仍然需要重新编译吗

    在场景2中,是否会为基本A重构vtable,从而为B和C重构vtable


    我知道场景3将强制B类和C类为新方法提供实现。因此,必须重新编译整个层次结构。

    无论缺少
    A
    virtual
    析构函数,这里都有一个界面:

    接口是一个不应该被破坏的契约

    如果要扩展接口而不需要重新编译完整的代码库,可以使用继承和动态多态性检查:

    class AEx : public A {
    public:
       virtual void method3() = 0;
       virtual ~AEx() {}
    }; 
    
    在处理您可以执行的扩展的函数中

    void foo(A* pA) {
        AEx pAEx = dynamic_cast<AEx*>(pa);
        if(pAEx) {
           pAEx->method3();
        }
    }
    
    void foo(A*pA){
    AEx pAEx=动态铸型(pa);
    如果(pAEx){
    pAEx->method3();
    }
    }
    

    C++定义规则明确表明,如果要将它们链接在一起,则不同翻译单元(即文件)中的实体定义必须相同。因此,如果您更改了一个类的定义,公共的、私有的、

    virtual
    、非
    virtual
    ,无论什么,所有使用该定义的翻译单元都必须查看新的类定义。这需要重新编译它


    未执行此操作的情况已形成,但不需要诊断(链接器错误)。因此,您的项目可能看起来链接很好。事实上,它在某些情况下可能确实有效。但是没有任何东西可以保证它们在什么情况下可以工作,在什么情况下不能工作。

    类不会被编译;文件被编译。因此,如果您不告诉我们文件结构是什么,那么您的问题似乎不够明确。Nicol。说得好。我的意思是说3个文件,分别包含这3个类。我已经编辑了我的文章。ABI不是标准的一部分。每个编译器或平台都有自己的规则。然而,KDE是一个处理这个问题的项目,他们保持着良好的性能。还有一些工具可以帮助检查您所做的更改是否破坏了ABI或API。纯虚拟函数调用与任何其他虚拟函数调用没有区别。谢谢,我添加了虚拟析构函数。你提到过设计层次结构,但我的设计已经给出了。我只需要知道在基类B中添加一些东西(3个场景)的影响。@softwarelover,如前所述,您必须重新编译完整的代码库。我想这就是我想要的答案。是的,我看到每个场景中的翻译单位都在变化!“不这样做是错误的,但不需要诊断(链接器错误)。”这告诉我们通常应该如何采取预防措施。但是,Nicol,我还是想知道虚拟案例是否必须重新编译。如果通过添加虚拟函数进行任何修改,vtable不会被破坏吗?这不是强制重新编译整个层次结构吗?@softwarelover:“我仍然想知道,对于虚拟案例,重新编译是否是强制性的”,这将依赖于实现,并且可能随时发生更改。