使用派生类生成复合文字

Build compound literal with derived class

本文关键字:复合 文字 派生      更新时间:2023-10-16

我不理解‘案例5’中的行为(见Main):

  1. 为什么有一个复制构造函数被调用
  2. 为什么没有调用Deriv复制构造函数
  3. "Base*b"在foo中是否已损坏

类别/功能/主

#include <iostream>
struct Base
{
    void        hello(void) {
        std::cout << "this=" << (void*)this << std::endl; }
    Base() : i(42) {
        std::cout << "Base  CTOR ";
        this->hello(); }
    ~Base() {
        std::cout << "Base  DTOR ";
        this->hello(); }
    Base(Base const &src) : i(43) {
        std::cout << "Base  CCPY ";
        this->hello(); }
    Base        &operator=(Base const &rhs) = delete;
    int     i;
};
struct Deriv : public Base
{
    void        hello(void) {
        std::cout << "this=" << (void*)this << std::endl; }
    Deriv() : Base(), j(84) {
        std::cout << "Deriv CTOR ";
        this->hello(); }
    ~Deriv() {
        std::cout << "Deriv DTOR ";
        this->hello(); }
    Deriv(Deriv const &src) : Base(src),j(85) {
        std::cout << "Deriv CCPY ";
        this->hello(); }
    Deriv       &operator=(Deriv const &rhs) = delete;
    int     j;
};
void        foo(Base *b)
{
    std::cout << "        foo b = " << (void*)b
              << std::endl;
    return ;
}
void        bar(Base const &b)
{
    std::cout << "        foo b = " << (void*)&b
              << std::endl;
    return ;
}
int                         main(void)
{
    bar(Base());             // Case 1 (Ok)
    std::cout << std::endl;
    foo((Base[]){Base()});   // Case 2 (Same as Case 4)
    std::cout << std::endl;
    std::cout << std::endl;
    bar(Deriv());            // Case 3 (Ok)
    std::cout << std::endl;
    foo((Deriv[]){Deriv()}); // Case 4 (Same as Case 3)
    std::cout << std::endl;
    std::cout << std::endl;
    foo((Base[]){Deriv()});  // Case 5 (Partial copy, bad bad bad ?)
    return (0);
}

输出

Base  CTOR this=0x7fff5d477818
        foo b = 0x7fff5d477818
Base  DTOR this=0x7fff5d477818
Base  CTOR this=0x7fff5d477808
        foo b = 0x7fff5d477808
Base  DTOR this=0x7fff5d477808

Base  CTOR this=0x7fff5d4777f8
Deriv CTOR this=0x7fff5d4777f8
        foo b = 0x7fff5d4777f8
Deriv DTOR this=0x7fff5d4777f8
Base  DTOR this=0x7fff5d4777f8
Base  CTOR this=0x7fff5d477880
Deriv CTOR this=0x7fff5d477880
        foo b = 0x7fff5d477880
Deriv DTOR this=0x7fff5d477880
Base  DTOR this=0x7fff5d477880

Base  CTOR this=0x7fff5d4777d8
Deriv CTOR this=0x7fff5d4777d8
Base  CCPY this=0x7fff5d4777e8
        foo b = 0x7fff5d4777e8
Base  DTOR this=0x7fff5d4777e8
Deriv DTOR this=0x7fff5d4777d8
Base  DTOR this=0x7fff5d4777d8

编译器

Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

Base[]中的类类型数组是Base确切类型的元素数组。由于元素实际上被放置在数组内存中,因此没有空间包含不同的实际类型。

如果提供匹配的元素,则它们将被放置在阵列中。另一方面,如果提供不同的类型,编译器会检查从提供的类型转换为Base的方法。Base的复制构造函数是转换Deriv对象的有效方法。

如果要在数组中存储派生类型,则需要通过引用(指针)来存储它们。这允许分配正确的数组大小,而不考虑元素大小。