【问题标题】:c++ Multiple virtual nested functions [duplicate]c ++多个虚拟嵌套函数[重复]
【发布时间】:2021-05-19 23:56:09
【问题描述】:

如何在继承链上有多个虚函数? 为什么在 'MoreSpecific' 类中调用 this->Init() 会导致未解决的外部符号错误?

遇到此代码时,它将始终处理 MostSpecificA 或 MostSpecificB 的实例,然后应该能够访问子类实现。

class GenericInterface
{
public:
   virtual void Init() = 0; //virtual function
   virtual void Startup() = 0;
};

class MoreSpecific : public GenericInterface
{
   virtual void Init() = 0; //we cannot yet define Init implementation here, not enough information
   
   void Startup() { 
      this->Init(); //this throws unresolved external symbol error
   }

   //other shared functionality
};

class MostSpecificA : public MoreSpecific
{
   void Init() {
       //the implemention for MostSpecificA
   }
};

class MostSpecificB : public MoreSpecific
{
   void Init() {
       //the implemention for MostSpecificB
   }
};

编辑,实际上上面的代码确实有效。从构造函数调用 Init() 时发生错误。以下代码产生未解决的外部符号错误,这与我的代码中发生的情况相匹配。

class GenericInterface
{
public:
    virtual void Init() = 0; //virtual function

};

class MoreSpecific : public GenericInterface
{
public:
    virtual void Init() = 0; //we cannot yet define Init implementation here, not enough information

    MoreSpecific() {
        this->Init();
    }
    //other shared functionality
};

class MostSpecificA : public MoreSpecific
{
public:
    MostSpecificA() 
        : MoreSpecific()
    {

    }

    void Init() {
        //the implemention for MostSpecificA
    }
};

class MostSpecificB : public MoreSpecific
{
    void Init() {
        //the implemention for MostSpecificB
    }
};

【问题讨论】:

  • 请将错误信息复制粘贴到您的问题中,而不是转述它。
  • 对我来说看起来不错。当然,您显然没有显示 actual 代码,因为这不可能编译——类定义甚至不以分号结尾。
  • 你的代码sn-p编译了吗?类定义后缺少一些;。另外我假设您在尚未建立继承的构造函数中调用 Startup 函数。
  • 另一个问题是你的所有子类都通过隐式声明私有方法来隐藏这些公共方法。如果你想从外面使用它们,它们必须在课堂的公共部分。解决这个问题,以及分号问题,就可以了。 godbolt.org/z/PYo49b
  • 那么你不能在那里做,因为这个函数不存在。您的对象未完全构造。类MoreSpecific 不知道MostSpecificA 或任何其他子类,直到对象完全构造之后。只有 then 允许您通过 vtable 调用调用。除非你的类被声明为final,否则你不应该在构造函数或析构函数中调用虚函数。

标签: c++


【解决方案1】:

从构造函数/析构函数调用虚方法不使用虚调度,只是以非虚的方式调用方法。

所以:

virtual void Init() = 0;

MoreSpecific() { this->Init(); } // call MoreSpecific::Init, but no definition provided

Init一般是错误的模式,初始化应该直接在构造函数中进行,不要虚调用。

但如果你真的想使用Init,你必须创建一个工厂并在创建对象后调用Init,类似于:

template <typename T>
T Create()
{
    T res{};
    res.Init();
    return res;
}

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2023-04-03
    • 2015-09-29
    • 2019-01-01
    相关资源
    最近更新 更多