使用派生类构建复合文字

时间:2015-11-25 11:05:08

标签: c++

我不理解'案例5'中的行为(见主要):

  1. 为什么有一个名为?
  2. 的复制构造函数
  3. 为什么不调用Deriv复制构造函数?
  4. foo中'Base * b'是否已损坏?
  5. 类/功能/主

    #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
    

1 个答案:

答案 0 :(得分:1)

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

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

如果要将派生类型存储在数组中,则需要通过引用(指针)存储它们。无论元素大小如何,这都允许分配正确的数组大小。