【问题标题】:Compiler misses invalid constructor call and calls non-existant (or private) default constructor编译器错过了无效的构造函数调用并调用了不存在(或私有)的默认构造函数
【发布时间】:2017-11-25 23:44:11
【问题描述】:

我有一个继承自其他几个基类的类的构造函数:

Derived::Derived() :    MyRpc< Derived, DERIVED_RPC_CLASS_ID, true  > ( Derived::sServerName ),
                    MyEventSource<Derived>( *this ),
                    Smasher<Derived>( *this )

{ 
}

正在调用 Smasher 的默认构造函数。同样奇怪的是,如果我将 Smash 的默认构造函数设为私有或直接删除它,编译器仍然会生成一个公共默认构造函数并调用它。

这是我如何定义粉碎机的:

class SmasherBase
{
    SmasherBase()=delete;
    SmasherBase( const char *name)
    {}
    .
    .
};

template< typename ... >  class Smasher : public SmasherBase
{
    Smasher()=delete;
};

template< typename LocalServerRPC_T >
class Smasher<LocalServerRPC_T> : public SmasherBase
{
public:
    Smasher()=delete;
    Smasher( LocalServerRPC_T &localServer, const char *name ) : SmasherBase( name ),
                                                                    mLocalServer( localServer )
    {
        ....
    }

    ~Smasher()
    {
    }

    typedef Smasher<LocalServerRPC_T>   Smasher_t;

protected:
    LocalServerRPC_T    &mLocalServer;
};

我希望编译器会抱怨我没有调用现有的构造函数:

error: no matching function for call to 'Smasher<Derived>::Smasher(EksoCAT&)' 

但它很高兴地编译了上面的代码,然后在我的反对意见之上创建了一个默认构造函数。它还为基类创建和调用默认构造函数。

我什至尝试将默认构造函数设为私有,希望它至少会意识到它不应该在其位置创建编译器生成的默认构造函数,并且可能会抱怨构造函数是私有的。

没有这样的运气。代码愉快地生成了,当我运行时,我可以进入幻影默认构造函数。

我正在使用 GNU 4.8.3 C++ 编译器。我还清理、重建、搜索了这些文件的旧版本,以确保它们没有被使用,等等,但无济于事。

感谢大家的帮助和想法。

【问题讨论】:

  • 如果你能把代码缩减为minimal reproducible example,那将非常有用
  • 但是尝试调用已删除的默认构造函数的代码在哪里?到目前为止,您提供的代码甚至没有尝试使用默认构造函数。因此,删除它的事实不会导致任何错误。您声称“正在调用 Smasher 的默认构造函数”。那个电话在哪里?您的第一个代码引用使用Smasher&lt;Derived&gt;( *this ),这绝对是不是默认构造函数。
  • @AnT 你发现了我的问题。我什至不叫它。如果我先步入 Derived 的构造函数,然后再步入 Smasher 的构造函数,就会步入默认构造函数(为 Smasher 生成的编译器)。
  • @RSahu 谢谢,会的。这个想法逃脱了我......一秒钟
  • @Kevin Stallard:“它进入默认构造函数”是什么意思?您的默认构造函数被删除。怎么可能踏入其中?你到底看到了什么?

标签: c++ c++11


【解决方案1】:

我的心理调试技能告诉我,您的课程 Derived 继承自 Smasher&lt;Derived&gt;。在这种情况下,您对Smasher&lt;Derived&gt;(*this) 的调用实际上是在调用Smasher复制构造函数,它是您自己没有删除或定义的,因此编译器会很乐意为您生成一个。调试器几乎肯定不会向您显示被调用的确切构造函数。

【讨论】:

  • 对不起马克,我在这里没有更高的声誉。我想为你和AnT做点好事......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多