2013-11-22 33 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" */ 
}