2013-11-18 9 views
10
#include<iostream> 

class base 
{ 
    public: 
     virtual ~base(){std::cout << "base\n";} 
}; 
class derived : public base 
{ 
    private: 
     ~derived(){std::cout << "derived\n";} /* destructor is private */ 
}; 
int main() 
{ 
     base *pt= new derived; 
     delete pt; 
} 

Вышеупомянутая программа компилируется и работает нормально. Как вызываемый дескриптор производного класса называется private?Как вызвать деструктор производного класса в качестве приватного в следующей программе?

+0

Ожидаете ли вы ошибку времени компиляции или ошибку во время выполнения? –

+0

Я бы не ошиблась. Мне интересно узнать, как в приведенной выше программе деструктор получает вызов! (он не должен вызываться, поскольку он был объявлен в частном спецификаторе.) –

+0

Если его не следует вызывать, но вы все равно пытаетесь его вызывать, тогда в какой-то момент должна появиться ошибка. Я спрашиваю вас, в какой момент вы считаете разумным и целесообразным сигнализировать об этой ошибке. –

ответ

1

Это произойдет не только с деструкторами.

Вы можете переопределить любую виртуальную публичную функцию с помощью частного.

#include<iostream> 

class base 
{ 
    public: 
     virtual void x(){std::cout << "base\n";} 
}; 
class derived : public base 
{ 
    private: 
     void x(){std::cout << "derived\n"; base::x();} 
}; 
int main() 
{ 
     base *pt= new derived; 
     pt->x(); //OK 
     //((derived *)pt)->x(); //error: ‘virtual void derived::x()’ is private 
     derived *pt2= new derived; 
     //pt2->x(); //error: ‘virtual void derived::x()’ is private 
     ((base *)pt2)->x(); //OK 
} 

Поверхность/минус этого вы должны будете использовать указатель на базу для доступа к этому методу. Эта функция является одним из способов отделить открытый API от индивидуальной реализации.

Другими словами, ваш деструктор получает вызов, потому что он был объявлен как открытый в базе, и вы вызываете его через указатель на базу.

+0

Я вызываю указатель на базу, но поскольку он также был объявлен как виртуальный в базовом классе, он должен вызвать деструктор производного класса сначала перед деструктором базового класса. –

+0

точно. Ваша программа печатает «производные \ nbase \ n». «private» ключевое слово не означает, что эта функция не может быть вызвана. это означает, что он не может называться через открытый класс этого класса. Если в вашем случае вы напишете «производный» pt = new производный; delete pt; » вы получите ошибку. – fsw

+0

когда вы делаете базу * pt = новый полученный; вы делаете base pt-> destructor = производный-> деструктор; тогда pt-> destructor является общедоступным, когда вы вызываете его, он вызывает внутренне производный-> деструктор, который является приватным, но вызывается из того же класса – vivoconunxino

0

Это может быть удивительно, но если вы думаете об этом, это совершенно логично.

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

Во время выполнения виртуальный деструктор вызывается. Так как получается, что указатель на базу действительно указывает на производный объект, поэтому сначала нужно вызвать производный конструктор.
«Но это личное!» говорит вам. Правильно, однако, во время работы нет понятия публичного/частного. Итак, опять же, нет причин для чего-то плохого. Ошибка не генерируется.