3

以下是我的代码,

#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')。但我希望调用 child 的方法,因为我将方法指定为虚函数。

那我怎样才能调用子类的方法呢?谢谢你。

4

3 回答 3

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

当你这样做时,你传递的对象被分割成aTestClass并且它的身份丢失了,所以它现在表现得像 aTestClass并相应地调用方法。

要解决此问题,您希望t按照@Nick 的建议通过引用传递,或者(不推荐)通过指针传递。它现在将保留其身份并调用适当的函数,只要test标记为虚拟

编辑:固定拼接->切片..太多生化奇兵..

于 2012-12-17T02:24:18.430 回答
2

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

void pass(TestClass &t)

这样,将使用原始对象。

于 2012-12-17T02:23:18.867 回答
1

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

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

对于您的示例,复制构造函数的签名如下:

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)。

最后一点,在使用继承时,您应该始终声明虚拟析构函数。这将避免在对象被销毁时进行切片。

于 2012-12-17T05:27:16.967 回答