如果在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
void method3() {};
virtual void method3() {};
virtual void method3() = 0;
void method3() {};
virtual void method3() {};
virtual void method3() = 0;
void method3() {};
virtual void method3() {};
virtual void method3() = 0;
我知道场景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:“我仍然想知道,对于虚拟案例,重新编译是否是强制性的”,这将依赖于实现,并且可能随时发生更改。