How can I make the method of child be called: virtual keyword not working?

谁都会走 提交于 2019-12-20 02:14:01

问题


The following is my code,

#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;
}

When I run the code, the method('test') of base class is called. But I expect the method of child is called because I specified methods as virtual function.

Then how can I make method of child class be called ? Thank you.


回答1:


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

When you do this, the object you are passing gets sliced into a TestClass and its identity is lost, so it now behaves like a TestClass and calls the method accordingly.

To Fix this you want to pass t by reference as @Nick suggested, or (not recommended) by pointer. It will now retain its identity and call the appropriate function, as long as test is marked virtual

Edit: fixed spliced -> sliced .. too much bioshock..




回答2:


You need to change the parameter for a reference (or a pointer)

void pass(TestClass &t)

This way, the original object will be used.




回答3:


As noted above, this is a result of "slicing". The specific details of what occurs is as follows:

When arguments are passed by value, a copy of the argument is passed to the function. When this happens, a new object is constructed by calling the copy-constructor.

For your example, the copy-constructor has a signature as follows:

TestClass::TestClass(const TestClass&);

so, what really happens is something like the following (again, for your example):

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.

Obviously, since the variable t is instantiated as a TestClass, any member function calls will be from TestClass (and not ExtendedTest).

As a final note, you should always declare virtual destructors when using inheritance. This will avoid slicing when objects are destroyed.



来源:https://stackoverflow.com/questions/13907522/how-can-i-make-the-method-of-child-be-called-virtual-keyword-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!