2010-09-17 242 views
0

假設我有兩個歸類BaseDerived,即:無限循環

#include <iostream> 

    class Base { 
    public: 
     Base() 
      : m_name("Base") 
     { 
     } 

     virtual ~Base() 
     { 
     } 

     virtual void method (std::ostream & out) const 
     { 
      out << m_name << std::endl; 
     } 

    protected: 
     Base (std::string name) 
      : m_name(name) 
     { 
     } 

    private: 
     std::string m_name; 
    }; 

    class Derived : public Base { 
    public: 
     Derived() 
      : Base("Derived") 
     { 
     } 

     virtual ~Derived() 
     { 
     } 

     virtual void method (std::ostream & out) const 
     { 
      static_cast<const Base * const>(this)->method(out); 
     } 
    }; 

如果我打電話Derived::method(),我得到一個無限循環。

int main() 
{ 
Derived d; 
d.method(std::cout); 

return 0; 
} 

當然。我可以將static_cast<const Base * const>(this)->method(out);更改爲Base::method(out),一切都會正常運行,但我對此行爲背後的原因感興趣。 不應該都具有相同的行爲?

那麼有人可以解釋這裏發生了什麼嗎?

在附註中,我編寫了代碼g++ -Wall -Wextra -O2 -g foo.cpp -o foo。 有沒有機會獲得這種代碼的警告?

回答

6

也許你已經猜到了:static_cast<const Base * const>(this)->method(out);是一個虛擬調用,這意味着該函數在其內部被調用。在這種情況下,它會導致堆棧溢出。 Base::method(out)不是虛擬呼叫。

4

您聲明該成員函數爲虛擬。簡而言之,這意味着派生類的實現將在通過指向基類的指針訪問對象時被調用。