Конструктор копирования C ++ и конструктор по умолчанию - PullRequest
3 голосов
/ 29 января 2020

Я изучаю C ++ и нашел вывод, который на самом деле не понимаю.

#include <iostream>
using namespace std;

class A{
    public:
        A(){ cout << "A+" << endl;}
        A(const A&){ cout << "A(A)" << endl;}
        ~A(){cout << "A-" << endl;}
};

class B{
    public:
        B(){ cout << "B+" << endl;}
        B(const B&){cout << "B(B)" << endl;}
        ~B(){cout << "B-" << endl;}
    private:
        A a;
};

class C : public A{
    public:
        C(const B& b) : b1(b) { cout << "C+" << endl;}
        ~C(){ cout << "C-" << endl;}
    private:
        B b1,b2;
};

void test(A a){
    A m(a);
}

int main(){
    B b;
    C c(b);
    test(c);
    return 0;

}

вывод

A+
B+
A+
A+
B(B)
A+
B+
C+
A(A)
A(A)
A-
A-
C-
B-
A-
B-
A-
A-
B-
A-

Я имею в виду первый, B идет по умолчанию видит a мы получили член типа A и переходим к A, который A+, затем возвращается к B и печатает B+. То есть с B b;, чем C c(b) он переходит на C, см. Его публикацию c A идет к A и печатает A +, затем возвращается к получению члена B b1, b2 идет к B, а B имеет члена А и идет Аеган к А и печатает A+, и чем я не понимаю, почему B (B)? после этого B (B) я ничего не понимаю .. я пытаюсь это отладить, но это мне не очень помогло, может быть, кто-то может объяснить, почему это работает так?

Ответы [ 2 ]

4 голосов
/ 29 января 2020

Если я правильно понял ваш вопрос, вы пытаетесь понять вывод

A+
A+
B(B)
A+
B+
C+

, который соответствует этому объявлению

C c(b);

Класс C имеет базовый класс A

class C : public A{

Таким образом, конструктор класса A называется

A+

, тогда создается элемент данных b1

C(const B& b) : b1(b) { cout << "C+" << endl;}

Класс B, в свою очередь, имеет элемент данных A

class B{
    public:
        B(){ cout << "B+" << endl;}
        B(const B&){cout << "B(B)" << endl;}
        ~B(){cout << "B-" << endl;}
    private:
        A a;
};

Поэтому, когда вызывается конструктор копирования класса B, создается элемент данных a

A+
B(B)

В классе C есть еще один элемент данных из класс B. Это член данных b2. Таким образом, эти конструкторы называются

A+
B+

И наконец тело конструктора C получает управление

C+

Деструкторы получают управление в обратном порядке относительно порядка создания. objects.

Таким образом, вывод деструкторов объекта c выглядит следующим образом

C-
B-
A-
B-
A-
A-

Вы можете сделать вывод программы более четким с небольшими изменениями программы.

Например

#include <iostream>
using namespace std;

class A{
    public:
        A(){ cout << "A+" << endl;}
        A(const A&){ cout << "A(A)" << endl;}
        ~A(){cout << "A-" << endl;}
};

class B{
    public:
        B() : i( n++ ) { cout << "B+" << ' ' << i << endl;}
        B(const B&) : i( n++ ) {cout << "B(B)" << ' ' << i << endl;}
        ~B(){cout << "B-" << ' ' << i << endl;}
    private:
        size_t i;
        static size_t n;
        A a;
};

size_t B::n;

class C : public A{
    public:
        C(const B& b) : b1(b) { cout << "C+" << endl;}
        ~C(){ cout << "C-" << endl;}
    private:
        B b1,b2;
};

void test(A a){
    A m(a);
}

int main(){
    B b;

    std::cout << '\n';

    C c(b);

    std::cout << '\n';

    test(c);

    std::cout << '\n';
}

Выход этой обновленной программы:

A+
B+ 0

A+
A+
B(B) 1
A+
B+ 2
C+

A(A)
A(A)
A-
A-

C-
B- 2
A-
B- 1
A-
A-
B- 0
A-
1 голос
/ 29 января 2020

Давайте подробнее рассмотрим конструктор C (слегка переформатированный):

C(const B& b)
    :
    b1(b)
{
    cout << "C+" << endl;
}

Сначала будет вызван конструктор A, так как это базовый класс для C. При этом будет напечатано A+.

. Затем будет создан экземпляр элемента b1, который сначала напечатает A+ из-за элемента B::a, а затем B(B) в B тело конструктора копирования.

Тогда будет создан элемент b2 по умолчанию, который напечатает A+ (снова из-за элемента B::a), за которым следует B+.

Затем будет запущено тело конструктора C, которое выведет C+.


Конструктор C действительно эквивалентен этому (с добавленными комментариями):

C(const B& b)
    : A(),      // Prints A+
      b1(b),    // Prints A+ and B(B)
      b2()      // Prints A+ and B+
{
    cout << "C+" << endl;    // Prints C+
}

Надеюсь, это поможет увидеть, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...