определение оператора в базовом классе - PullRequest
1 голос
/ 17 февраля 2012

У меня есть следующий пример кода.класс bar является производным от базового класса foo и выделяет память для ptr_x, в то время как доступ для чтения / записи предоставляется через базовый класс.Это игрушечная модель для большого кода, в которой функции чтения / записи одинаковы для всех различных вариантов объекта, но распределение памяти немного отличается в разных вариантах.

#include <iostream>

class foo{
protected:
    int *ptr_x;

public:
    foo(){
        std::cout << " 1) Inside foo constructor: " << ptr_x << std::endl;
    }

    void read() 
    {
        std::cout << " 2) Inside read function: " <<  ptr_x << std::endl;    
        std::cout << " 3) Inside read function: " << *ptr_x << std::endl;
    }
    void operator=(const int rhs)
    {
        std::cout << " 4) Inside operator= : " <<  ptr_x << std::endl;
        *ptr_x = rhs;
    }        
};
class bar: public foo{

public:
    bar(int a)
    : foo()
    {
        std::cout << " 5) Inside bar constructor: " << ptr_x << std::endl;
        ptr_x = new int;
        std::cout << " 6) Inside bar constructor: " << ptr_x << std::endl;
        *ptr_x = a;
    }
    ~bar()
    {
        std::cout << " 7) Inside bar destructor: " << ptr_x << std::endl;
        if (ptr_x != NULL) {delete ptr_x; ptr_x = NULL;}
    }
};
int main (){
    bar a(20);
    a.read();
    a = 40;
    a.read();
    return 0;
}

Когда я запускаю код, яget:

 1) Inside foo constructor: 0
 5) Inside bar constructor: 0
 6) Inside bar constructor: 0x1d8f010
 2) Inside read function: 0x1d8f010
 3) Inside read function: 20
 1) Inside foo constructor: 0x7f40c11e3b68
 5) Inside bar constructor: 0x7f40c11e3b68
 6) Inside bar constructor: 0x1d8f030
 7) Inside bar destructor: 0x1d8f030
 2) Inside read function: 0x1d8f030
 3) Inside read function: 0
 7) Inside bar destructor: 0x1d8f030
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0000000001d8f030 ***

У меня есть следующие вопросы: 1) Почему код не вводит operator= в базовом классе?2) Почему второй вызов сделан конструктору / деструктору?3) почему существует проблема double free?

что я здесь не так делаю?

РЕДАКТИРОВАТЬ: ОК double free проблема очевидна, но почему два экземпляра с одинаковыми расположениями памяти?Это как-то связано с operator=, так как, когда я закомментирую это, все в порядке.

Спасибо

Ответы [ 2 ]

2 голосов
/ 17 февраля 2012

Обоснование наблюдаемого поведения:

Компилятор использует конструктор преобразования в производном классе,

  bar(int a)

для оценки:

  a = 40;

Он принимает целое число 40 и создает объект bar, используя конструктор преобразования, а затем назначает созданный объект bar для a, используя оператор неявного копирования (=), сгенерированный компилятором. для класса bar.

По этой причине вы видите дополнительные вызовы конструктора bar, а перегруженный базовый класс = никогда не вызывается. Кроме того, причина двойного освобождения заключается здесь: у вас есть несколько bar объектов, которые продолжают указывать на динамическую память, выделенную для ptr_x, и когда один из объектов выходит из области видимости, вызывается деструктор, который освобождает память, но оставляет указатель члена другого объекта в висячем состоянии.

Как решить эти проблемы:
Вы должны пометить конструктор преобразования явный , если вы не хотите, чтобы компилятор использовал его для неявных преобразований, подобных этой.

Вы должны следовать правилу трех для своего класса bar.

Оговорка:
Обратите внимание, что оператор = в базовых классах всегда скрыт неявно сгенерированным оператором = для производного класса.

1 голос
/ 17 февраля 2012

Для первого вопроса вы должны были объявить bar (int a) как

explicit bar(int a).

. Это дает правильную ошибку компиляции, что в строке классов должен быть определен оператор =.

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