C ++中main函数的继承初始化

时间:2013-12-24 11:04:37

标签: c++ class inheritance

从过去几周开始,我正在学习和试验C ++中的继承和多态。

很少有语法让我理解,主要是从main函数调用对象。

例如:

#include <iostream.h>

using namespace std;

class Base
{
public:
    Base(){ cout<<"Constructing Base";}

virtual ~Base(){ cout<<"Destroying Base";}
};

class Derive: public Base
{
    public:
    Derive(){ cout<<"Constructing Derive";}

    ~Derive(){ cout<<"Destroying Derive";}
};

void main()
{
    Base *basePtr = new Derive();

    delete basePtr;
 }

这是我的问题:

Base * basePtr = new Derive(); 这个语法被调用时会发生什么?有什么好处?

据我所知,我理解它调用派生类对象并将其存储在指向基类对象的指针中。我对么?如果我是,为什么要将它存储在基类中?

为了清除我的怀疑,我经历了类对象的内存布局和反汇编,但它让我更加困惑。

有谁能告诉我如何理解这种语法?

4 个答案:

答案 0 :(得分:1)

当您使用指向基类对象的指针而不是指向派生类的指针时,您说您只需要此派生类的BASIC属性。

答案 1 :(得分:1)

公共继承意味着派生类的每个对象都是基类的对象(它提供了基类具有的所有接口)。所以,当你写:

Base *basePtr = new Derive();

创建了类Derive的新对象,而不是将指向它的指针分配给basePtr,通过basePtr,您可以访问类提供的所有功能{。}}。

如果你随后调用任何Base类虚函数,如:

Base

将调用实际对象类中的函数,就像主函数末尾的析构函数一样。

答案 2 :(得分:0)

嗯......指针在开始时很混乱。

当您致电Base *basePtr = new Derive();时,您正在创建一个Derive对象实例,只保留此对象所在位置的“书签”,但使用Base指针。

当你这样做时,唯一可访问的属性(没有强制转换)将来自Base类。

为什么要使用它?抽象的东西。想象一下,你正在编写与杯子,杯子,眼镜和水壶有关的东西。基本上所有类型的这些物体都用于储存某种液体。所以我将调用基类LiquidContainer

class LiquidContainer
{
  //...
};

class Mug : public LiquidContainer
{
  //...
};

class Glass : public LiquidContainer
{
  //...
};

class Cup : public LiquidContainer
{
  //...
};

class Jug : public LiquidContainer
{
  //...
};

所有其他人都继承自LiquidContainer,尽管Jug,Cup和Mug可以在更复杂的继承树中创建。

无论如何,拥有基类并使用多态的目的是避免代码复制和抽象,这样就可以对所有LiquidContainer族进行几乎相同的处理。

以示例为例,提供更完整的类定义。

class LiquidContainer
{
public:
  LiquidContainer(unsigned int capacity, unsigned int color) : 
    mCapacity(capacity), 
    mColor(color) 
  {
  }

  unsigned int getCapacity() { return mCapacity; }
  unsigned int getColor() { return mColor; }
  virtual char* name() = 0;

protected:
  unsigned int mCapacity;
  unsigned int mColor;
};

class Mug : public LiquidContainer
{
public:
  Mug() :
    LiquidContainer( 250, 0xFFFF0000 ) // 250 ml yellow mug!
  {
  }

  virtual char* name() { return "Mug"; }
};

class Glass : public LiquidContainer
{
public:
  Glass() :
    LiquidContainer( 200, 0x000000FF ) // 200 ml transparent glass!
  {
  }

  virtual char* name() { return "Glass"; }
};

class Cup : public LiquidContainer
{
public:
  Cup() :
    LiquidContainer( 50, 0xFFFFFF00 ) // 50 ml white cup!
  {
  }

  virtual char* name() { return "Cup"; }
};

class Jug : public LiquidContainer
{
public:
  Jug() :
    LiquidContainer( 1500, 0x0000FF00 ) // 1.5 l blue Jug!
  {
  }

  virtual char* name() { return "Jug"; }
};

使用这些类定义,您可以执行以下测试:

#include <iostream>
#include <vector>

int main( int argc, char* argv[] )
{
  std::vector< LiquidContainer* > things;

  things.push_back( new Mug() );
  things.push_back( new Cup() );
  things.push_back( new Glass() );
  things.push_back( new Jug() );

  for ( auto container : things )
  {
    std::cout << "This is a '" << container->name() << "' with capacity of " << container->getCapacity() << "ml and color " << container->getColor() << std::endl;
  }

  return 0;
}

这个小程序输出

This is a 'Mug' with capacity of 250ml and color 4294901760
This is a 'Cup' with capacity of 50ml and color 4294967040
This is a 'Glass' with capacity of 200ml and color 255
This is a 'Jug' with capacity of 1500ml and color 65280

我希望这个小练习足以向您展示为何使用多态。

答案 3 :(得分:0)

这叫做Polymorphism。这意味着该对象是Derive和Base,可以同时用作两者。例如。如果Dog是Animal的子类。狗的对象也可以被视为动物。所有的狗都是动物,但不是所有的动物都是狗。

因此,您可以将狗称为动物,这就是为什么您可以将子类对象(Derive)的地址赋予超类指针(Base)。但它仍将是子类的一个对象,并将像一个一样运行。这只是为了让编译器理解它是Base的一个对象。

现在好处是你可以有一个方法可以接受Base类的对象(或精确意义上的指针),但是可以传递它的任何子类。这里的con是你只能调用基类中的方法,并且可以在derive类中重写或不重写。