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

使用using导入构造函数为何会导致重载决议选择不同的重载版本?

Why does using Base::Base change overload resolution for Derived's constructors?

Great question! The behavior you're seeing comes down to a specific rule in C++ about inherited constructors (those imported via using declarations) and how they interact with compiler-generated special member functions. Let's break this down step by step.

What's happening when you explicitly declare Derived's constructors (#if 1)

When you write:

Derived(const Base& other) : Base(other) {}
Derived(const BaseBase& other) : Base(other) {}

You're explicitly defining two constructors for Derived:

  • Derived(const Base&): Takes a const Base& and forwards it to Base's copy constructor (which sets test = 1).
  • Derived(const BaseBase&): Takes a const BaseBase& and forwards it to Base's constructor that takes const BaseBase& (which sets test = 2).

When you call Derived d1{b1} where b1 is a Base, overload resolution picks the exact match (const Base&), so test is set to 1—this matches your expectation.

What changes when you use using Base::Base (#if 0)

When you import base class constructors with using Base::Base, C++ applies some important rules that you might not be aware of:

1. Compiler-generated copy constructor blocks importing Base's copy constructor

The C++ standard states that inherited constructors (from using declarations) are not imported if they would conflict with a special member function that the compiler generates automatically for the derived class.

In your case, since you didn't declare a copy constructor for Derived, the compiler generates a default copy constructor:

Derived(const Derived&) = default;

This generated copy constructor counts as a "corresponding copy constructor" to Base's copy constructor (Base(const Base&)). As a result, the Base(const Base&) constructor is not imported into Derived.

2. Only non-conflicting base constructors are imported

The only constructors imported into Derived are:

  • Derived(): From Base's default constructor.
  • Derived(const BaseBase&): From Base's constructor taking const BaseBase& (since there's no conflicting compiler-generated constructor for this signature).

3. Overload resolution has no exact match

When you call Derived d1{b1} now, there's no Derived(const Base&) constructor available (it wasn't imported). The only candidate is Derived(const BaseBase&), which accepts b1 via a derived-to-base conversion (since Base inherits from BaseBase). This constructor forwards to Base(const BaseBase&), setting test = 2—hence your return value of 2.

Summary of the key rule

When using using Base::Base to inherit constructors:

  • Inherited constructors that would act as the derived class's default, copy, or move constructor are not imported if the compiler generates that special member function automatically.
  • This means Base's copy constructor doesn't become part of Derived's overload set, leaving only the BaseBase& constructor to handle the Base argument via conversion.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 07:23:12