从过去几周开始,我正在学习和试验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(); 这个语法被调用时会发生什么?有什么好处?
据我所知,我理解它调用派生类对象并将其存储在指向基类对象的指针中。我对么?如果我是,为什么要将它存储在基类中?
为了清除我的怀疑,我经历了类对象的内存布局和反汇编,但它让我更加困惑。
有谁能告诉我如何理解这种语法?
答案 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类中重写或不重写。