我对继承和多态的概念感到困惑。我的意思是,代码重用性和功能覆盖之间有什么区别?是否无法使用继承概念重用父类函数,否则无法使用Polymorphism覆盖父类变量。对我来说似乎没什么区别。
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
我怀疑代码重用和函数覆盖之间的区别。
答案 0 :(得分:2)
让我们从你的例子开始。
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
继承:这里你从类A派生出B类,这意味着你可以访问它的所有公共变量和方法。
a = a + 1
您正在使用a
的变量class A
,您正在重用a
中的变量class B
,从而实现代码可重用性。
多态性处理程序如何根据必须执行的操作调用方法:在您的示例中,您使用get()
的{{1}}覆盖class A
的方法get()
1}}。因此,当您创建B类实例和调用方法时,您将在控制台中获得class B
而不是'hi'
答案 1 :(得分:2)
函数继承允许从“更具体”的派生类到“更抽象”的基类的行为抽象。 (这类似于基本数学和代数中的因子。)在这种情况下,更抽象只是意味着指定的细节更少。期望派生类将扩展(或添加到)基类中指定的内容。例如:
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
private:
int m_commonProperty;
};
class Subtype1 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
char getProperty(void) const { return m_specificProperty1; }
private:
char m_specificProperty1;
};
class Subtype2 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
float getProperty(void) const { return m_specificProperty2; }
private:
float m_specificProperty2;
};
请注意,在上面的示例中,getCommonProperty()
和setCommonProperty(int)
是从CommonBase
类继承的,可以在Subtype1
和{{类型的对象的实例中使用1}}。所以我们在这里有继承,但我们还没有真正的多态性(将在下面解释)。
您可能希望也可能不希望实例化基类的对象,但您仍然可以使用它来收集/指定所有派生类将继承的行为(方法)和属性(字段)。因此,对于代码重用,如果您有多种类型的派生类共享某些常见行为,则可以在基类中仅指定该行为一次,然后在所有派生中“重用”该行为类而不必复制它。例如,在上面的代码中,Subtype2
和getCommmonProperty()
的规范可以说是由每个setCommonProperty(int)
类重用,因为不需要为每个方法重写这些方法。
多态性是相关的,但它意味着更多。它基本上意味着您可以以相同的方式处理碰巧来自不同类的对象,因为它们都恰好来自(扩展)公共基类。为了真正有用,该语言应该支持虚拟继承。这意味着函数签名在多个派生类中可以是相同的(即,签名是公共抽象基类的一部分),但是根据特定的对象类型将执行不同的操作。
因此修改上述示例以添加到Subtype#
(但保持CommonBase
和Subtype1
与之前相同):
Subtype2
请注意,class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
virtual void doSomething(void) = 0;
virtual ~CommonBase() { }
private:
int m_commonProperty;
};
在doSomething()
中声明为纯虚函数(这意味着您永远不能直接实例化CommonBase
对象 - 它不一定是这个方式,我只是这样做,以保持简单)。但是现在,如果你有一个CommonBase
对象的指针,可以 一个CommonBase
或一个Subtype1
,你可以拨打Subtype2
。这将根据对象的类型执行不同的操作。这是多态性。
doSomething()
就您在问题中提供的代码示例而言,void foo(void)
{
CommonBase * pCB = new Subtype1;
pCB->doSomething();
pCB = new Subtype2;
pCB->doSomething(); // Does something different...
}
被称为“覆盖”的原因是因为该方法的get()
版本中指定的行为优先于(“覆盖”)如果您在B::get()
对象的实例上调用A::get()
(即使您是通过get()
执行此操作,则在方法的B
版本中指定的行为,因为方法在类A*
)中声明为virtual
。
最后,关于“代码重用”的其他评论/问题并不像你指定的那样有效(因为它不在方法中),但我希望如果你参考我上面写的内容就会很清楚。当您从公共基类继承行为并且您只需要为该行为编写一次代码(在基类中),然后所有派生类都可以使用它,那么这可以被认为是一种“代码重用”。
答案 2 :(得分:0)
您可以在没有继承的情况下使用参数多态。在C ++中,这是使用模板实现的。维基文章:
http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29#Parametric_polymorphism