You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

这种选择性构造函数“继承”方式是否符合C++标准?

C++选择性继承基类构造函数的标准合规性解析

问题场景

尝试实现仅继承基类部分构造函数时,在GCC上可通过以下方式实现:

#include <string>
#include <iostream>

struct B
{
    B()
    {
        std::cout << std::string("B::B() called") << std::endl;
    }

    B(int)
    {
        std::cout << std::string("B::B(int) called") << std::endl;
    }

    B(long)
    {
        std::cout << std::string("B::B(long) called") << std::endl;
    }


    B(long, long)
    {
        std::cout << std::string("B::B(long, long) called") << std::endl;
    }
};


struct D : public B
{
    D(int) = delete;
    D(long, long)
    {
        std::cout << std::string("D::D(long, long) called") << std::endl;
    }

    using B::B;
};



#pragma GCC diagnostic push // Ignore warnings from unused variables
#pragma GCC diagnostic ignored "-Wunused-variable"
int main()
{
    B b0;
    B b1(1);
    B b2(1, 2);
    D d0;
    // D d1(1);   error despite we might wish B::B(long) to be selected
    D d2(1, 2);
}
#pragma GCC diagnostic pop

具体做法是:通过using B::B引入基类所有构造函数,再在派生类中通过delete声明或自定义构造函数的方式,覆盖不需要的重载。同时发现using声明和派生类构造函数的声明顺序不影响结果。

核心疑问:

  1. 这种实现方式是否符合C++标准?
  2. using声明顺序无关的特性是否符合标准?

注:该方式并非完全意义上的选择性继承,因为被delete的重载仍会参与重载解析(如注释行D d1(1)会报错,而非匹配基类的B(long)构造函数)。

解答

1. 该实现方式符合C++标准

根据C++标准,using Base::Base会将基类的所有构造函数引入到派生类的作用域中,与派生类自身声明的构造函数共同组成重载集合。当派生类中存在与基类构造函数签名完全匹配的构造函数(包括delete声明的版本)时,重载解析会优先匹配派生类的版本:

  • 对于自定义的D(long, long),调用D(1,2)时会直接匹配该构造函数,而非基类的版本;
  • 对于D(int)=delete,调用D(1)时,int类型实参会精确匹配这个被删除的构造函数,触发编译错误,而不会去匹配需要隐式转换的B(long)。

这种通过派生类声明覆盖基类继承构造函数的行为,是标准允许的。

2. using声明顺序不影响结果也符合标准

在C++类的作用域中,成员的声明顺序不会影响重载解析的最终结果。无论是先声明派生类自己的构造函数,还是先写using B::B,最终派生类作用域内的所有构造函数(包括引入的基类构造函数和自定义/delete的版本)都会被纳入同一个重载集合。重载解析仅依据函数签名的匹配度,而非声明顺序,所以顺序的不同不会改变最终的匹配结果。

内容的提问来源于stack exchange,提问作者skyking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:03:27