【问题标题】:Call derived class method from base class reference从基类引用调用派生类方法
【发布时间】:2011-05-11 16:11:48
【问题描述】:
class Material
{
public:
 void foo()
 {
  cout << "Class Material";
 }
};

class Unusual_Material : public Material
{
public:
 void foo()
 {
  cout << "Class Unusual_Material";
 }
};

int main()
{
 Material strange = Unusual_Material();
 strange.foo(); //outputs "Class Material" 

 return 0;
}

我希望这会导致“Class Unusual_Material”显示在控制台上。有没有办法可以做到这一点?在我的程序中,我有一个 Material 类,从中派生出其他更具体的材料。方法 Material::foo() 表示 Material 中适用于大多数材料的方法,但有时,需要为具有不寻常属性的材料定义另一个 foo()。

我的程序中的所有对象都包含一个 Material 字段。如果为它们分配了不寻常的材料,我希望调用派生的、不寻常的 foo。

这可能很容易,或者不可能,但我无法弄清楚。

谢谢

【问题讨论】:

标签: c++ derived-class base-class


【解决方案1】:

您想要的是多态性,并且要为某个功能启用它,您需要将其设为virtual:

class Material 
{ 
public: 
    virtual void foo() // Note virtual keyword!
    { 
        cout << "Class Material"; 
    } 
}; 

class Unusual_Material : public Material 
{ 
public: 
    void foo() // Will override foo() in the base class
    { 
        cout << "Class Unusual_Material"; 
    } 
}; 

此外,多态性仅适用于引用和指针:

int main()  
{  
    Unusual_Material unusualMaterial;
    Material& strange = unusualMaterial;
    strange.foo();  
    return 0; 
}

/* OR */

int main()  
{  
    Unusual_Material unusualMaterial;
    Material* strange = &unusualMaterial;
    strange->foo();  
    return 0; 
}

您的代码 sn-p 中的内容将 slice the Unusual_Material object:

int main() 
{ 
    // Unusual_Material object will be sliced!
    Material strange = Unusual_Material(); 
    strange.foo(); 
    return 0; 
} 

【讨论】:

  • 啊!谢谢你指出这一点。我想我忘记了 virtual 不仅仅是定义一个抽象类。感谢您的快速回复!
  • @user487100:没关系,只要你意识到出了什么问题。不过,我确实建议您选择a good C++ book,因为它将更详细地介绍这个基本主题。
  • 我也不知道切片。我认为该程序将无法访问派生部分,但我想,当不使用引用时,这很有意义。感谢您在最后添加这一点以启发我。
  • @user487100:这与您不能将派生类的对象“拟合”到基类的对象中这一事实有关,因为派生类几乎总是有更多数据成员。在某种程度上,您无法访问派生部分,因为这些派生部分已被截断,以便编译器可以将派生类对象分配给基类对象。
  • @user487100:但是,无论是指向派生类还是基类的指针,指针和引用的大小都是相同的,因此使用指针和引用不会出现切片问题。
【解决方案2】:

更好的解释是......

class Base
{
public:
 void foo()     //make virtual void foo(),have derived method invoked
 {
  cout << "Class Base";
 }
};
class Derived: public Base
{
public:
 void foo()
 {
  cout << "Class Derived";
 }
};
int main()
{
 Base base1 = Derived ();
 Base1.foo(); //outputs "Class Base" 
           // Base object, calling base method

 Base *base2 = new Derived ();
 Base2->foo(); //outputs"Class Base",Again Base object calling base method

// But to have base object, calling Derived method, following are the ways
// Add virtual access modifier for base foo() method. Then do as below, to //have derived method being invoked.
//
// Base *base2 = new Derived ();
// Base2->foo();    //outputs "Class Derived" .

return 0;
}

【讨论】:

    猜你喜欢
    • 2014-03-17
    • 2016-07-06
    • 2014-02-15
    • 2013-03-28
    • 2013-04-11
    • 2016-01-01
    • 2013-03-23
    • 2015-04-08
    • 1970-01-01
    相关资源
    最近更新 更多