c – 转发构造函数调用2次基类的复制构造函数

前端之家收集整理的这篇文章主要介绍了c – 转发构造函数调用2次基类的复制构造函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下代码将构造函数从base转发为派生类.

为什么2个复制构造函数调用?在后台发生了什么?

用g编译.

#include <iostream>
using namespace std;

struct A {
    A() { cout << "A" << endl; }
    A(const A&) { cout << "A(const A&)" << endl; }
    template<typename T> A(T a); // Needed to compile :-O
};

template<typename T>
struct C : public T { using T::T; };

int main()
{
    A a;
    C<A> ca(a);
    //C<A> caa(ca);
    return 0;
}

输出是:

A
A(const A&)
A(const A&)

解决方法

通过在A中定义构造函数模板,C将被赋予具有类似签名的构造函数模板.它隐含地定义为:
template<typename T>
struct C : public T
{
    //using T::T;

    C() = default;
    C(C const&) = default;

    template<typename U> C(U a) : T( std::forward<U>(a) ) {}
};

这现在调用A的复制构造函数两次:一次用于按值获取参数.第二个调用来自T(std :: forward< U>(a))调用A的copy-ctor.这对我来说是令人惊讶的,因为你期望一个继承的ctor调用基类的确切ctor.它已被继承.但事实并非如此,重载决策不是选择A的ctor模板,而是选择普通复制器A(A const&)(见下文).

有趣的是,它并不关心A中构造函数模板的作用,只需要声明它.这就是为什么在OP中,定义可能会丢失;它也可以删除(这可能是一个缺陷?).

只需在初始化T的重载解析期间选择A的复制器(std :: forward< U>(a)).这是这种情况:参数是类型A的右值,它可以直接绑定到const A&参考,根据A的复制者的要求.由于引用绑定是直接的,没有派生到基本的转换,因此复制者排名为完全匹配. A中的ctor模板也被列为精确匹配,但由于模板和非模板函数在重载集中具有相同的等级,因此非模板函数是首选(复制函数A(A const& ;)).

原文链接:https://www.f2er.com/c/119914.html

猜你在找的C&C++相关文章