[C++]现代C++语言核心特性解析 Chapter 13

继承构造函数(C++11)

1 使用继承构造函数

C++中可以使用using关键字将基类的函数引入派生类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base {
public:
void foo(int) {}
};

class Derived : public Base {
public:
using Base::foo;
void foo(char*) {}
};

int main()
{
Derived d;
d.foo(5);
}

C++11的继承构造函数正是利用了这一点,将using关键字的能力进行了扩展,使其能够引入基类的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Base {
public:
Base() : x_(0), y_(0.) {};
Base(int x, double y) : x_(x), y_(y) {}
Base(int x) : x_(x), y_(0.) {}
Base(double y) : x_(0), y_(y) {}
private:
int x_;
double y_;
};

class Derived : public Base {
public:
using Base::Base;
};

注意事项

  • 派生类是隐式继承基类的构造函数,所以只有在程序中使用了这些构造函数,编译器才会为派生类生成继承构造函数的代码。

  • 派生类不会继承基类的默认构造函数和复制构造函数。这一点乍看有些奇怪,但仔细想想也是顺理成章的。因为在C++语法规则中,执行派生类默认构造函数之前一定会先执行基类的构造函数。同样的,在执行复制构造函数之前也一定会先执行基类的复制构造函数。所以继承基类的默认构造函数和默认复制构造函数的做法是多余的,这里不会这么做。

  • 继承构造函数不会影响派生类默认构造函数的隐式声明,也就是说对于继承基类构造函数的派生类,编译器依然会为其自动生成默认构造函数的代码。

  • 在派生类中声明签名相同的构造函数会禁止继承相应的构造函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class Base {
    public:
    Base() : x_(0), y_(0.) {};
    Base(int x, double y) : x_(x), y_(y) {}
    Base(int x) : x_(x), y_(0.) { std::cout << "Base(int x)" << std::endl; }
    Base(double y) : x_(0), y_(y) { std::cout << "Base(double y)" << std::endl; }
    private:
    int x_;
    double y_;
    };

    class Derived : public Base {
    public:
    using Base::Base;
    Derived(int x) { std::cout << "Derived(int x)" << std::endl; }
    };

    int main()
    {
    Derived d(5);
    Derived d1(5.5);
    }

    派生类Derived使用using Base::Base继承了基类的构造函数,但是由于Derived定义了构造函数Derived(int x),该函数的签名与基类的构造函数Base(int x)相同,因此这个构造函数的继承被禁止了,Derived d(5)会调用派生类的构造函数并且输出”Derived(int x)”。另外,这个禁止动作并不会影响到其他签名的构造函数,Derived d1(5.5)依然可以成功地使用基类的构造函数进行构造初始化。

  • 派生类继承多个签名相同的构造函数会导致编译失败

  • 继承构造函数的基类构造函数不能为私有


[C++]现代C++语言核心特性解析 Chapter 13
https://erlsrnby04.github.io/2024/11/01/C-现代C-语言核心特性解析-Chapter-13/
作者
ErlsrnBy04
发布于
2024年11月1日
许可协议