2016-03-13 102 views
3

我已经在cpp中编写代码来测试我对动态调度的理解。我认为在我的程序中输出应该是“我在NT”。我的理由是:动态调度OOP

  1. tMethod被定义为虚拟的,所以动态绑定将用于
  2. 在运行时类类型的test是NT,所以打电话test->tMethod(ont)应该寻找里面NT
  3. 实施
  4. 实际参数ont的类型是NT的,所以找到精确匹配是tMethod
  5. 的NT的impementation

不过,这一方案的输出为“我T中我”。

我的推理出了什么问题?

#include <iostream> 

    using namespace std; 

    class T { 

     public: 
      virtual void tMethod(T){ 
       cout<<"I'm in T"<<endl; 
      } 

    }; 

    class NT: public T{ 
     public: 
      void tMethod(NT){ 
       cout<<"I'm in NT"<<endl; 
      } 

    }; 


    int main() 
    { 
     NT ont; 

     T* test=new NT(); 

     test->tMethod(ont); 

     return 0; 
    } 
+1

'NT :: tMethod()'采用不同的参数类型到'N :: tMethod()',所以它不会覆盖。使用'override'关键字来防止这种情况 – Galik

+0

尽管如此,也许在这个例子中,他不能使用任何多态的能力,并且可能会遇到未定义的行为,因为他通过价值传递了它。例如,切片。 – Incomputable

+1

@OlzhasZhumabek这不会是未定义的行为,除非这些类在其实现中存在UB错误。 – juanchopanza

回答

5

这种方法:

void tMethod(NT){ 

不会覆盖这一个:从NT

virtual void tMethod(T){ 

您已经更改参数类型T

您可以添加覆盖关闭这个将其误入错误:

void tMethod(NT) override { 

将输出:

main.cpp:16:18: error: 'void NT::tMethod(NT)' marked 'override', but does not override void tMethod(NT) override {

[编辑]

你的实际问题是为什么C++不允许重载跨类的传承的功能,具体地,涉及能够访问使用碱衍生类函数类指针。原因是语言不支持此功能。您可以在Bjarne Stroustrup常见问题解答中找到类似的问题:Why doesn't overloading work for derived classes?

+0

为什么它需要覆盖它?我同意这不是重新定义(我认为这是超载)。但NT类仍然有两种方法,一种是继承的,另一种是NT类型的新方法。现在在我的情况下,当查找适当的函数时,为什么当实际参数是NT类型时,选择了类型T的形式参数的函数? – balboa

+0

'test-> tMethod(ont);'在类类型T的指针上进行函数调用,这意味着只会调用T中的方法。将'T * test'改为'NT * test'并且'void tMethod(NT)'将被调用。 – marcinj

+0

它是类类型T的指针,但在运行时它指向类类型NT。不应该在NT内搜索方法吗?我认为这是多态的主要思想。 – balboa

2

NT::tMethod()采用不同的参数类型为N::tMethod(),因此它不会覆盖。使用override关键字,以防止这一点:

#include <iostream> 

using namespace std; 

class T 
{ 

public: 
    virtual void tMethod(T) { 
     cout << "I'm in T" << endl; 
    } 
}; 

class NT: public T 
{ 
public: 
    void tMethod(NT) override { // use override keyword here 
     cout << "I'm in NT" << endl; 
    } 
}; 

int main() 
{ 
    NT ont; 

    T* test = new NT(); 

    test->tMethod(ont); 

    return 0; 
} 

现在你应该得到一个编译错误,因为你标记MT::tMethod()override但由于它采用了不同的参数类型没有。

1

你最好使用指针或引用基类作为虚方法中的一个参数。如果您需要在overriden方法中使用派生类,那么您可以使用dynamic_cast。

class T { 

    public: 
     virtual void tMethod(T*){ 
      cout<<"I'm in T"<<endl; 
     } 

}; 

class NT: public T{ 
    public: 
     virtual void tMethod(T* t) override { 
      NT* nt=dynamic_cast<NT*>(t); 
      if (nt) 
      { 
       cout<<"I'm in NT as NT"<<endl; 
      } 
     }  
}; 


int main() 
{ 
    NT ont; 

    T* test=new NT(); 

    test->tMethod(&ont); 

    return 0; 
}