在调用基类之前需要在成员上调用方法

Posted

技术标签:

【中文标题】在调用基类之前需要在成员上调用方法【英文标题】:Need to call method on member before calling base class 【发布时间】:2019-09-19 00:26:25 【问题描述】:

我有类似下面的代码:

template<class BASE_TYPE = COdbcQuery>
class CRemoteQuery : public BASE_TYPE

    CRemoteDatabase m_Db;

public:
    CRemoteQuery()
        : BASE_TYPE(&m_Db)
    
    

    ~CRemoteQuery()
    
    
;

我的问题是必须在将m_Db 传递给基本构造函数之前调用m_Db.Open()

如果我调用一个方法作为调用Open() 的基本构造函数的参数,它会失败,因为m_Db 尚未初始化。

我尝试在基类中创建一个虚方法,它会在初始化期间被调用并且这个类可以覆盖,但是模板类不能覆盖虚拟方法。

重组我的基类以使m_Db 不需要首先打开会引发很多难题。有没有办法做到这一点?

【问题讨论】:

虽然我同意@Sam Varshavchik,但我认为它突出了另一个问题。鉴于职责分离,CRemoteQuery 类应该处理数据库的打开,还是应该使用 依赖注入 为您提供已经打开的数据库?我会选择后者,但您可以像这样轻松地使用逗号运算符:BASE_TYPE((static_cast&lt;void&gt;(m_Db.Open()), &amp;m_Db)) @jfh:我什至不确定如何使用 DI 来解决这个问题。此类通过在我只需要查询时管理自己的数据库来节省大量输入。无论如何,我试图在我的问题中解释我尝试了你的建议。但是如果因为m_Db还没有被构造而失败。 @Johnathan Wood 好吧,您可以尝试在相同的逗号运算符表达式ala 位置new 中显式构造m_Db,但这也是一个很大的代码气味。 IMO 这可能表明您应该重构和引入工厂等,因为您获得生命周期不确定的资源的想法闻起来......很臭。 【参考方案1】:

只需稍作改动即可轻松实现这一系列事件:

class CRemoteDB 

protected:
    CRemoteDatabase m_Db;

    CRemoteDB()
    
          m_Db.open();
    
;

template<class BASE_TYPE = COdbcQuery>
class CRemoteQuery : private CRemoteDB, public BASE_TYPE


public:
    CRemoteQuery()
        : BASE_TYPE(&m_Db)
    
    

    ~CRemoteQuery()
    
    
;

父类总是按声明顺序构造的。首先构造CRemoteDB父类,然后在父类的构造函数中调用CRemoteDatabase::open()

然后BASE_TYPE被构造,并获得指向打开的m_Db的指针。

CRemoteQuery 可以从其父类访问m_Db,与它是它自己的类成员时没有什么不同。

但是模板类不能覆盖虚方法。

附:谁告诉你那是错的。模板类当然可以覆盖虚拟方法。我在这里有大量的模板层次结构,所有覆盖其父类的虚拟方法,左右。

【讨论】:

另一种可能的解决方案可能是创建一个方法,执行此类初始化,并使用它的结果传递给基类,例如:auto&amp; initAndReturn m_Db.open (); return m_db; CRemoteQuery () : BASE_TYPE (&amp;initAndReturn ()) 谢谢,虽然一个奇怪的修复这似乎是最好的答案。至于虚拟方法,我尝试从基类覆盖一个虚拟方法,但它从未被调用。当我用谷歌搜索时,我发现了像this这样的页面。 @AlgirdasPreidžius:正如我的问题中所述,我尝试过,但它失败了,因为 m_Db 尚未构建。 @JonathanWood 嗯.. 由于您所描述的原因,我考虑过此类代码是否是未定义的行为。但是,我想,我记得看到过类似的代码,而且它似乎工作正常。也许我的大脑在欺骗我,我记错了。我可能需要去然后睡觉:/ @AlgirdasPreidžius 取决于您如何使用该成员,这可能并不重要——例如,缓存对我稍后将使用的东西的引用。数据库的初始化逻辑,太丑了。

以上是关于在调用基类之前需要在成员上调用方法的主要内容,如果未能解决你的问题,请参考以下文章

调用派生类的构造函数在基类的构造函数之前执行

c++继承总结

C#关键字学习

Razor Pages - 在所有 OnGet 处理程序之后从基类调用方法

如何在基类上调用显式实现的接口方法

派生类调用使用非继承成员的继承函数