隐式复制构造函数和继承

3

我知道这种问题已经被问了很多次,我也读过不同的答案,以及ISO标准的一些部分。
但是,我仍然需要澄清一些关于C++标准要求的确切行为的问题。

假设情况是这样的:

class A
{
    public:

        A( void ) {}
        A( const A & a ) {}
};

class B: public A
{
    public:

        B( void ) {}
        B( const B & b ) {}
};

我知道调用B类的复制构造函数不会调用A类的复制构造函数,我们可以使用初始化列表来正确实现。

我还知道使用using来继承构造函数。

但是,如果派生类没有显式提供复制构造函数,而基类有,标准到底要求什么:

class A
{
    public:

        A( void ) {}
        A( const A & a ) {}
};

class B: public A
{};

我一直认为编译器会隐式地为类B定义一个复制构造函数,从而隐藏类A的复制构造函数,因此不会调用它。
然而,看起来情况并非如此,在OS X 10.10上使用Clang编译时,会调用A的复制构造函数。
那么这是强制性的还是可以由实现定义的呢?这意味着我们不应该依赖这种行为吗?
在C++标准中,我找到了以下内容,但对我来说显然不是非常清晰:
“当使用odr-used(3.2)创建其类类型的对象(1.8)时,将隐式定义一个类的继承构造函数。隐式定义的继承构造函数执行将由使用声明的嵌套名称说明符中指定的基类命名的mem-initializer-id的mem-initializer-list的用户写入的内联构造函数的初始化集合以及下面指定的表达式列表,并且其函数体中的复合语句为空(12.6.2)。”
我真的很想得到关于它的澄清,根据标准,也考虑到多重继承。
1个回答

3

来自http://en.cppreference.com/w/cpp/language/copy_constructor(我强调):

隐式定义的复制构造函数

如果隐式声明的复制构造函数既没有被删除也不是平凡的,那么如果odr-used,则编译器将定义它(即生成并编译函数体)。对于联合类型,隐式定义的复制构造函数将对象表示形式复制一遍(例如通过std::memmove)。对于非联合类类型(类和结构体),构造函数执行对象的基类和非静态成员的完全逐成员复制,按照它们的初始化顺序使用直接初始化。

因此,似乎编译器生成的复制构造函数将调用基本复制构造函数,就像它调用成员的复制构造函数一样。


1
此外,继承构造函数与此无关,因为复制构造函数永远不会被继承,而继承的构造函数也不会阻止正确的复制构造函数生成。 - Sebastian Redl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接