繁体   English   中英

如果将虚函数或非虚函数添加到C ++中的基类中,是否必须重新编译整个类层次结构?

[英]Must the entire class hierarchy be recompiled if a virtual or non-virtual function is added to the base class in C++?

我试图了解一个类的vtable在C ++中的敏感程度,为此,我需要知道对于下面列出的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() {} 
};

这是我的情况:

  1. 非虚拟方法被添加到基类A:

     void method3() {}; 
  2. 具有主体的虚拟方法被添加到基类A中:

     virtual void method3() {}; 
  3. 将纯虚拟方法添加到基类A:

     virtual void method3() = 0; 

在方案1中,不对vtable进行任何更改。 是否仍然需要重新编译B和C?

在方案2中,是否会针对基数A并因此针对B和C重构vtable?

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

C ++一键定义规则清楚地表明,如果要将它们链接在一起,则不同翻译单元(即文件)中实体的定义必须全部相同。 这样,如果您完全更改了一个类的定义, 无论是 public,private, virtual ,non- virtual 还是what ,使用该定义的所有翻译单元都必须查看新的类定义。 这将需要重新编译。

失败的原因是不正确的,但是不需要诊断(链接程序错误)。 因此,您的项目似乎可以很好地链接。 确实,在某些情况下它实际上可能起作用。 但是没有任何东西可以保证它们在某些情况下会起作用,而在某些情况下它们不会起作用。

无论缺少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();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM