如果将虚函数或非虚函数添加到 C++ 中的基 class,是否必须重新编译整个 class 层次结构?
Must the entire class hierarchy be recompiled if a virtual or non-virtual function is added to the base class in C++?
我正在尝试了解 class 的 vtable 在 C++ 中有多敏感,为此,我需要知道是否重新编译整个 class 层次结构(总共 3 个头文件) 对于我在下面列出的 3 个变更场景是必需的。首先,这是我的 class 层次结构:
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() {}
};
这是我的场景:
一个非虚拟方法添加到基class A:
void method3() {};
一个带主体的虚方法被添加到基class A:
virtual void method3() {};
基础上增加了一个纯虚方法class A:
virtual void method3() = 0;
在场景 1 中,没有对 vtable 进行任何更改。 B和C还需要重新编译吗?
在场景 2 中,是否会为基 A、B 和 C 重建 vtable?
我知道场景 3 将强制 classes B 和 C 提供新方法的实现。因此,必须重新编译整个层次结构。
尽管 A
缺少 virtual
析构函数,您在这里有一个 接口:
class A {
public:
virtual void method1() = 0;
virtual void method2() = 0;
virtual ~A() {} // This is needed
};
接口是一个不应该被打破的契约。
如果您想扩展接口而不需要重新编译完整的代码库,您可以使用继承和动态多态性检查:
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();
}
}
C++ one-definition-rule 清楚地表明,如果您要 link 他们在一起。因此,如果您完全更改 class、public、private、virtual
、non-virtual
、whatever,所有使用该定义的翻译单元都必须查看新的 class 定义。这将需要重新编译它。
未能做到这一点是 il-formed,但不需要诊断 (linker-error)。所以你的项目可能看起来 link 就好了。事实上,它在某些情况下可能确实有效。但是没有什么可以保证它们在哪些情况下会起作用,在哪些情况下不会起作用。
我正在尝试了解 class 的 vtable 在 C++ 中有多敏感,为此,我需要知道是否重新编译整个 class 层次结构(总共 3 个头文件) 对于我在下面列出的 3 个变更场景是必需的。首先,这是我的 class 层次结构:
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() {}
};
这是我的场景:
一个非虚拟方法添加到基class A:
void method3() {};
一个带主体的虚方法被添加到基class A:
virtual void method3() {};
基础上增加了一个纯虚方法class A:
virtual void method3() = 0;
在场景 1 中,没有对 vtable 进行任何更改。 B和C还需要重新编译吗?
在场景 2 中,是否会为基 A、B 和 C 重建 vtable?
我知道场景 3 将强制 classes B 和 C 提供新方法的实现。因此,必须重新编译整个层次结构。
尽管 A
缺少 virtual
析构函数,您在这里有一个 接口:
class A {
public:
virtual void method1() = 0;
virtual void method2() = 0;
virtual ~A() {} // This is needed
};
接口是一个不应该被打破的契约。
如果您想扩展接口而不需要重新编译完整的代码库,您可以使用继承和动态多态性检查:
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();
}
}
C++ one-definition-rule 清楚地表明,如果您要 link 他们在一起。因此,如果您完全更改 class、public、private、virtual
、non-virtual
、whatever,所有使用该定义的翻译单元都必须查看新的 class 定义。这将需要重新编译它。
未能做到这一点是 il-formed,但不需要诊断 (linker-error)。所以你的项目可能看起来 link 就好了。事实上,它在某些情况下可能确实有效。但是没有什么可以保证它们在哪些情况下会起作用,在哪些情况下不会起作用。