理解虚函数和指针用法

时间:2015-12-20 12:29:01

标签: c++ polymorphism

在理解切片之后,据我所知,它可以使用指向动态变量的指针来破解。但是怎么了?为什么那时没有切片?我想自己,但我不确定。在ppet = pdog;任务之后,pdog指向ppet的相同地址。不是吗?

//Program to illustrate use of a virtual function 
//to defeat the slicing problem.

#include <string>
#include <iostream>
using namespace std;

class Pet
{
public:
    virtual void print();
    string name;    
};

class Dog : public Pet
{     
public: 
    virtual void print();//Keyword virtual not needed, but put
                         //here for clarity. (It is also good style!)

string breed;
};

int main()
{
    Dog vdog;
    Pet vpet;

    vdog.name = "Tiny"; 
    vdog.breed = "Great Dane";
    vpet = vdog; 

    //vpet.breed; is illegal since class Pet has no member named breed

    Dog *pdog;
    pdog = new Dog;
    pdog->name = "Tiny";
    pdog->breed = "Great Dane";

    Pet *ppet; 
    ppet = pdog; 
    ppet->print(); // These two print the same output:
    pdog->print(); // name: Tiny breed: Great Dane

    //The following, which accesses member variables directly
    //rather than via virtual functions, would produce an error:
    //cout << "name: " << ppet->name << "  breed: " 
    //     << ppet->breed << endl;
    //generates an error message: 'class Pet' has no member
    //named 'breed' .
    //See Pitfall section "Not Using Virtual Member Functions"
    //for more discussion on this.

    return 0;
}

void Dog::print()
{
    cout << "name: " << name << endl;
    cout << "breed: " << breed << endl; 
}

void Pet::print()

{
    cout << "name: " << endl;//Note no breed mentioned
}

输出:

The slicing problem:
name: Tiny
Note that it was print from Pet that was invoked.
The slicing problem defeated:
name: Tiny
breed: Great Dane
name: Tiny
breed: Great Dane

2 个答案:

答案 0 :(得分:3)

派生类本质上是“开始”其基类的实例,后跟派生类添加的任何其他字段。所以:

class Base {
    int a, b;
};

class Derived {
    int c, d;
};

Derived实例在内存中看起来像这样:

[a] [b]|[c] [d]

如果您现在将其“切片”到Base实例中,则会发生这种情况:

[a] [b]|nothing

另一方面,指向对象的指针总是大小相同,无论类型如何,因此指向基类的指针可以指向派生对象而不会丢失任何信息。 Base对象的Derived部分的开头与Derived对象本身的地址完全相同。

答案 1 :(得分:0)

定义类时,其成员定义其内存布局。类数据成员按顺序存储在存储器中。

当您派生类并使用继承时,派生类的数据成员只需添加到基类的数据成员之后。

因此,当切片发生时,你就会有效地&#34;看到&#34;只有基类成员。

  

现在,关于&#34;为什么指针oto基类没有切片派生类的对象&#34;

继承最重要的一个方面不是它为派生类提供成员函数,而是它提供了在派生类和基类之间表达的关系。派生类可以被视为&#34;基类的一种类型&#34;

如需进一步阅读,请查看向上转播向下转换这两个词。

向上转换正在将派生类引用或指针转换为基类。换句话说,向上转换允许我们将派生类型视为它的基类型。

  

要从评论部分回答您的问题,&#34;什么是覆盖?

从a派生与虚拟函数具有相同名称和类型的函数 基类,称为重写