2013-11-22 31 views
2

我很困惑......似乎這兩件事情都做同樣的事情。我覺得我很混淆名稱隱藏與功能覆蓋

在這第一個代碼中,我相信派生類隱藏了基類的函數名。

#include <iostream> 

using namespace std; 

class Quadrilateral { 

public: 
    void greeting() { 
     std::cout << "i am a quadrilateral" << std::endl; 
    } 
}; 

class Square : public Quadrilateral { 
public: 
    void greeting() { 
     std::cout << "i am a square" << std::endl; 
    } 
}; 

class Trapezoid : public Quadrilateral { 

public: 
    void greeting() { //hides greeting from quadrilateral function 
     std::cout << "Hi I'm a Trapezoid" << std::endl; 
    } 
}; 

int main() 
{ 
    Trapezoid tz; 
    tz.greeting(); 
} 

這似乎有完全相同的結果:在這裏,他們被重寫,因爲它是虛擬的基類]

#include <iostream> 
using namespace std; 


class Quadrilateral { 

public: 

    virtual void greeting() { 
     std::cout << "i am a quadrilateral" << std::endl; 
    } 
}; 

class Square : public Quadrilateral { 
    public: 
    void greeting() { 
     std::cout << "i am a square" << std::endl; 
    } 
}; 

class Trapezoid : public Quadrilateral { 

public: 
    void greeting() { //hides greeting from quadrilateral function 
     std::cout << "Hi I'm a Trapezoid" << std::endl; 
    } 
}; 

int main() 
{ 
    Trapezoid tz; 
    tz.greeting(); 
} 

所以我想我來真的很迷茫。 ..有什麼不同?或者,如果它在這種情況下會產生相同的效果,那麼在基類中使它變爲虛擬的點是什麼?

+2

第二並不能掩蓋它,但覆蓋它。 –

+0

我知道,但它似乎做同樣的事情,無論你重寫或隱藏它。那麼有什麼意義呢? @LuchianGrigore – FrostyStraw

+1

在這兩種情況下試試這個:製作派生類的實例。用基類的類型製作一個指針。調用基類指針(實際上指向派生類的實例)的函數。 – BoBTFish

回答

0

在C++中,如果在本例中聲明/有一個結構體或類變量,編譯器會平凡地知道它的類型,並且始終調用正確的函數,而不管虛擬/否。

虛擬函數只在處理指針或引用時很重要。

嘗試主要在年底前加入這個你現有的代碼之後,:

Quadrliateral *q = &t; 
q->greeting(); 

而且你會發現它是相當重要的所有問候的功能是否是虛擬的或沒有。

+0

好的。誠然,我應該知道這一點。然而,我仍然有點困惑,究竟能夠通過使用基類型指針來使用派生類型對象的好處是什麼?喜歡......我能從中得到什麼?我唯一注意到的不同是,如果派生類有一個沒有在基類中定義的函數,並且你創建了一個派生類對象的基指針,那麼不在基類中的派生類的函數就不是更長的訪問。這給了我什麼好處? @RichardPlunkett – FrostyStraw

+0

我想有時你想要一個指向任何四邊形的指針,但不在乎它是方形還是梯形。 – Moberg

1

虛函數用於從基類指針調用overriden函數。 隨着你的第二個例子中,你可以得到同樣的結果,如果你中main()

Trapezoid tz; 
Quadrilateral *base = &tz; 
base->greeting(); // it will print "Hi I'm a Trapezoid" 

以下這是第一個例子的區別是:可能從基類指針調用派生功能。 如果您不覆蓋派生類中的虛擬基礎函數,則將調用基礎虛擬函數。

使用示例。

試想一下,要與基類Quadrilateral(例如5個方塊了三個梯形)創建了很多對象:現在

Square sq1, sq2, sq3, sq4, sq5; 
Trapezoid tz1, tz2, tz3; 

,在代碼中的某個點,你想要去扔掉所有的這個對象並且調用抽象函數(在你的情況下爲greeting())。所以,在虛函數的幫助下,你可以做到這一點非常簡單:將所有對象放在一個指針數組中,並調用propper函數。下面是如何:你會

Quadrilateral *base[8] = {&sq1, &sq2, &sq3, &sq4, &sq5, &tz1, &tz2, &tz3}; 
for (int i = 0; i < 8; i++) { 
    base[i]->greeting(); 
} 

在輸出收到五次"i am a square"三次"Hi I'm a Trapezoid"。 當您創建所有不同的形狀(例如具有不同的尺寸,屬性)並且想要拋出所有這些對象並調用時,它會有所不同,例如,calc()函數可以爲每個形狀進行單獨計算。

我希望這可以幫助你。

0

首先,請格式化您的代碼!

第一示例

class Quadrilateral { 
    public: 
    void greeting() { 
     std::cout << "i am a quadrilateral" << std::endl; 
    } 
}; 

class Square : public Quadrilateral { 
    void greeting() { 
    std::cout << "i am a square" << std::endl; 
    } 
}; 

class Trapezoid : public Quadrilateral { 
    public: 
    void greeting() { //hides greeting from quadrilateral function 
     std::cout << "Hi I'm a Trapezoid" << std::endl; 
    } 
}; 

int main() { 
    Trapezoid tz; 
    tz.greeting(); 
} 

在這個例子中是完全正常的Trapezoid.greeting()隱藏Quadrilateral.greeting():它是一個首要(相同方法名,相同的回報,相同的參數(無) )。

第二示例

class Quadrilateral { 
    public: 
    virtual void greeting() { 
    std::cout << "i am a quadrilateral" << std::endl; 
    } 
}; 

class Square : public Quadrilateral { 
    void greeting() { 
    std::cout << "i am a square" << std::endl; 
    } 
}; 

class Trapezoid : public Quadrilateral { 
public: 
    void greeting() { //hides greeting from quadrilateral function 
    std::cout << "Hi I'm a Trapezoid" << std::endl; 
    } 
}; 

int main() { 
    Trapezoid tz; 
    tz.greeting(); 
} 

相同。您創建了具有動態類型梯形的靜態類型Trapezoid的objcet。所以tz.greeting會打印出「我是梯形的」,因爲greeting()是一個覆蓋。

第三個例子

class Shape { 
    public: 
    virtual void greeting() { 
     std::cout << "Shape" << std::endl; 
    } 
}; 

class Square : public Shape { 
    /* override method greeting() of Shape class */ 
    void greeting() { 
    std::cout << "Square" << std::endl; 
    } 
}; 

class Triangle : public Shape { 
    public: 
    /* override method greeting() of Shape class */ 
    void greeting() { 
     std::cout << "Triangle" << std::endl; 
    } 
}; 

int main() { 
    Shape* shape = new Triangle(); 
    shape->greeting(); /* prints "Triangle" */ 
    shape = new Square(); 
    shape->greeting(); /* prints "Square" */ 
}