如何调用子方法:虚拟关键字不起作用?

时间:2012-12-17 02:21:54

标签: c++ object-slicing

以下是我的代码,

#include<iostream>
#include<string>

using namespace std;

class TestClass
{
  public:
    virtual void test(string st1, string st2);

};

class ExtendedTest: public TestClass
{
  public:
    virtual void test(string st1, string st2);
};

void TestClass::test(string st1, string st2="st2")
{
     cout << st1 << endl;
     cout << st2 << endl;
}

void ExtendedTest::test(string st1, string st2="st2")
{
     cout << "Extended: " << st1 << endl;
     cout << "Extended: " << st2 << endl;
}

void pass(TestClass t)
{
    t.test("abc","def");
}


int main()
{
   ExtendedTest et;
   pass(et);
   return 0;
}

当我运行代码时,会调用基类的方法('test')。 但我希望调用子方法,因为我将方法指定为虚函数。

然后如何调用子类的方法?谢谢。

3 个答案:

答案 0 :(得分:3)

void pass(TestClass t)
{
    t.test("abc","def");
}

执行此操作时,您传递的对象会TestClass TestClass并且其身份会丢失,因此它现在的行为类似于t并相应地调用该方法。< / p>

要修复此问题,您希望通过引用传递test作为@Nick建议,或者(不推荐)通过指针传递。只要{{1}}标记为虚拟

,它现在将保留其身份并调用相应的函数

编辑:固定拼接 - &gt;切片..生化奇兵太多了..

答案 1 :(得分:2)

您需要更改参考(或指针)的参数

void pass(TestClass &t)

这样,将使用原始对象。

答案 2 :(得分:1)

如上所述,这是“切片”的结果。发生的具体细节如下:

当参数按值传递时,参数的副本将传递给函数。发生这种情况时,通过调用copy-constructor构造一个新对象。

对于您的示例,copy-constructor具有如下签名:

TestClass::TestClass(const TestClass&);

所以,真正发生的事情就像下面这样(再次,对于你的例子):

ExtendedTest et();
pass(et);
{ // entering scope of pass function ...
  TestClass t = TestClass(t_orig); // inserted by the compiler
  // evaluation of pass function ...
  // ...
} // leaving scope of pass function, t is destroyed.

显然,由于变量t被实例化为TestClass,因此任何成员函数调用都来自TestClass(而不是ExtendedTest)。

最后请注意,在使用继承时,应始终声明虚拟析构函数。当对象被破坏时,这将避免切片。