2016-04-20 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
c++中 析构函数中不可以调用虚函数。
effective C++ 中有这样的描述:同样的原因也适用于析构过程。一旦派生类析构函数运行,这个对象的派生类数据成员就被视为未定义的值,所以 C++ 就将它们视为不再存在。
C++中派生类在构造时会先调用基类的构造函数再调用派生类的构造函数,析构时则相反,先调用派生类的析构函数再调用基类的构造函数。
假设一个派生类的对象进行析构,首先调用了派生类的析构,然后在调用基类的析构时,遇到了一个虚函数,这个时候有两种选择:Plan A是编译器调用这个虚函数的基类版本,那么虚函数则失去了运行时调用正确版本的意义;Plan B是编译器调用这个虚函数的派生类版本,但是此时对象的派生类部分已经完成析构,“数据成员就被视为未定义的值”,这个函数调用会导致未知行为。
effective C++ 中有这样的描述:同样的原因也适用于析构过程。一旦派生类析构函数运行,这个对象的派生类数据成员就被视为未定义的值,所以 C++ 就将它们视为不再存在。
C++中派生类在构造时会先调用基类的构造函数再调用派生类的构造函数,析构时则相反,先调用派生类的析构函数再调用基类的构造函数。
假设一个派生类的对象进行析构,首先调用了派生类的析构,然后在调用基类的析构时,遇到了一个虚函数,这个时候有两种选择:Plan A是编译器调用这个虚函数的基类版本,那么虚函数则失去了运行时调用正确版本的意义;Plan B是编译器调用这个虚函数的派生类版本,但是此时对象的派生类部分已经完成析构,“数据成员就被视为未定义的值”,这个函数调用会导致未知行为。
展开全部
很简单,你定义一个虚函数,然后在析构函数中调用看看,debug调试,能运行就证明可以!
自己动手比实践,比问别人“记住”一些规则,更有效果!
自己动手比实践,比问别人“记住”一些规则,更有效果!
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
根据Effective C++ (3rd Edition) ---- Item 9:
Never call virtual functions during construction or destruction.
(不要在构造函数和析构函数中调用虚函数)
其中举例为:(英文)
class Transaction {
public:
Transaction();
virtual void LogTransaction() const = 0;
// ...
};
Transaction::Transaction()
{
// ...
LogTransaction();
}
class BuyTransaction : public Transaction {
public:
virtual void LogTransaction() const;
// ...
};
Consider what happen when this code is executed:
BuyTransaction b;
Clearly a BuyTransaction constructor will be called, but firt, a Transaction constructor must be called; base class parts of derived class objects are constructed before derived class parts are. The last line of the Transaction constructor calls the virtual function longTransaction, but this is where the surprise comes in. The version of logTransaction that't called is the one in Transaction, not the one in BuyTransaction -- even though the type of object being created is BuyTransaction. During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type. Informally speaking, during base class construction, virtual functions aren't.
There's a good reason for this seemingly counterintuitive behavior. Because base class constructors execute before derived class constructors, derived class data members have not been initialized when base class constructors run. If virtual functions called during base class construction went down to derived classes, the derived class functions would almost certainly refer to local data members, but those data members would not yet have been initialized. That would be a non-stop ticket to undefined behavior and late-night debugging sessions. Calling down to parts of an object that have not yet been initialized is inherently dangerous. so C++ gives you no way to do it.
根据上面的原文看:调用的结果是(可能发生未定义行为)
这是由于(上例中)在BuyTransaction构造函数执行时,先执行基类(Transaction)的构造函数,而在Transaction的构造函数中又调用了(纯)虚函数logTransaction(),由于现在是在派生类里边定义函数,所以调用的logTransaction是BuyTransaction()里边的函数。这样有违背了你的初衷(调用Transaction里边的logTransaction())...
如果在虚函数里边有对派生类成员(不是从基类那里继承来的)的操作,那么更遭,以为在调用基类构造函数调时(派生类的成员还没有被初始化),这样就会导致未定义行为。
你最好看看原文的解释(英文部分)!
总之,记住不要在构造函数(析构函数)中调用虚函数!
Never call virtual functions during construction or destruction.
(不要在构造函数和析构函数中调用虚函数)
其中举例为:(英文)
class Transaction {
public:
Transaction();
virtual void LogTransaction() const = 0;
// ...
};
Transaction::Transaction()
{
// ...
LogTransaction();
}
class BuyTransaction : public Transaction {
public:
virtual void LogTransaction() const;
// ...
};
Consider what happen when this code is executed:
BuyTransaction b;
Clearly a BuyTransaction constructor will be called, but firt, a Transaction constructor must be called; base class parts of derived class objects are constructed before derived class parts are. The last line of the Transaction constructor calls the virtual function longTransaction, but this is where the surprise comes in. The version of logTransaction that't called is the one in Transaction, not the one in BuyTransaction -- even though the type of object being created is BuyTransaction. During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type. Informally speaking, during base class construction, virtual functions aren't.
There's a good reason for this seemingly counterintuitive behavior. Because base class constructors execute before derived class constructors, derived class data members have not been initialized when base class constructors run. If virtual functions called during base class construction went down to derived classes, the derived class functions would almost certainly refer to local data members, but those data members would not yet have been initialized. That would be a non-stop ticket to undefined behavior and late-night debugging sessions. Calling down to parts of an object that have not yet been initialized is inherently dangerous. so C++ gives you no way to do it.
根据上面的原文看:调用的结果是(可能发生未定义行为)
这是由于(上例中)在BuyTransaction构造函数执行时,先执行基类(Transaction)的构造函数,而在Transaction的构造函数中又调用了(纯)虚函数logTransaction(),由于现在是在派生类里边定义函数,所以调用的logTransaction是BuyTransaction()里边的函数。这样有违背了你的初衷(调用Transaction里边的logTransaction())...
如果在虚函数里边有对派生类成员(不是从基类那里继承来的)的操作,那么更遭,以为在调用基类构造函数调时(派生类的成员还没有被初始化),这样就会导致未定义行为。
你最好看看原文的解释(英文部分)!
总之,记住不要在构造函数(析构函数)中调用虚函数!
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
是可以的,不过,这样调用没有什么意义,不能实现多态。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询