简体   繁体   English

多态与向下转换

[英]Polymorphism vs DownCasting

Let's say I have a Base class Employee and an derived class Manager , like below:假设我有一个基类Employee和一个派生类Manager ,如下所示:

class Employee
{
public:
    string Name;  
};

class Manager : public Employee
{
public:
    string Designation;
};

While implementing some function like below:在实现如下功能时:

Employee* SomeFunction(bool SomeCondition)
{
    Employee *Emp = NULL;
    if (SomeCondition) 
    {
       //Code goes here : Both Implementation 1 and 2 work fine!          
    }              
    return Emp;
}

When SomeCondition is true, I want to return a non-null object of type Manager .SomeCondition为真时,我想返回一个类型为Manager的非空对象。 In such a scenario, both below pieces of code seem to fit the bill:在这种情况下,以下两段代码似乎都符合要求:

Implementation 1:实施1:

Manager *Mng = new Manager;
Mng->Name = "Adam";
Mng->Designation = "BOSS";
Emp = Mng;

Implementation 2:实施2:

Emp = new Manager;
Manager *Mng = (Manager*)Emp;
Mng->Name = "Adam";
Mng->Designation = "BOSS";

Since both work just fine, I would like to know which one among the two is the more efficient one?既然两者都工作得很好,我想知道两者中哪一个更有效?

Which one is using the concept of Polymorphism?哪一个使用了多态的概念?

Is the type casting in Implementation 2 a down-cast?实现 2 中的类型转换是向下转换吗? Is it good practice?这是好的做法吗?

Both of your implementations do what you want them to, however the second one is very bad practice.您的两个实现都按照您的意愿行事,但是第二个实现是非常糟糕的做法。

First, let's clear up a misconception you seem to have: In your second implementation, you're not doing what is usually considered a downcast.首先,让我们澄清一个你似乎有的误解:在你的第二个实现中,你没有做通常被认为是沮丧的事情。 You're using a C-style cast (see http://en.cppreference.com/w/cpp/language/explicit_cast ), which will, among casting away things such as const , happily cast any pointer to a Manager* .您正在使用 C 风格的强制转换(请参阅http://en.cppreference.com/w/cpp/language/explicit_cast ),它会在丢弃诸如const之类的东西中,愉快地将任何指针强制转换为Manager* For example, you might just as well do例如,你也可以这样做

Manager *Mng = (Manager*) new Employee; // not a good idea

or even甚至

Manager *Mng = (Manager*) new int; // now, this is really bad...

As a general rule, you should never use C-style casts in C++.作为一般规则,您永远不应该在 C++ 中使用 C 风格的强制转换。


You can do a safe downcast in C++ by using dynamic_cast :您可以使用dynamic_cast在 C++ 中进行安全的向下转换:

Manager *Mng = dynamic_cast<Manager*>(ptr_to_manager);  // will return a pointer to the Manager object
Manager *Mng = dynamic_cast<Manager*>(ptr_to_employee); // will return nullptr

Still, there is runtime overhead needed to check whether your cast is actually safe (ie, distinguish the first case in the example from the second).尽管如此,仍需要运行时开销来检查您的强制转换是否真正安全(即,区分示例中的第一种情况和第二种情况)。 The need for a downcast is, by the way, usually an indication of bad design.顺便说一句,需要向下转型通常表明设计不佳。


In short, the first implementation is the easier and obvious way to go: no need for an downcast, safe or unsafe.简而言之,第一个实现是更容易和明显的方式:不需要向下,安全或不安全。

While I see some reasons behind your questions, I think you need to improve the your example虽然我看到了你的问题背后的一些原因,但我认为你需要改进你的例子

  • you are saying that you need to return a non-null object of type "Manager", while your define "SomeFunction(bool SomeCondition)" to return "Employee".你是说你需要返回一个“Manager”类型的非空对象,而你定义“SomeFunction(bool SomeCondition)”来返回“Employee”。

  • if you are indeed going to return "Employee" object why bothering initializing "Designation" while you will not be able to access it later.如果您确实要返回“Employee”对象,为什么还要在以后无法访问它的情况下还要初始化“Designation”呢。 For example:例如:

     cout << SomeFunction(true)->Designation(); // error !

So, I'm not sure what do mean by saying your examples work fine, since the context is not clear.所以,我不确定说你的例子工作正常是什么意思,因为上下文不清楚。

** Comparing Implementation 1 and 2 / About dynamic casting ** 比较实现 1 和 2 / 关于动态转换

While both examples can improve, I think Implementation 1 is slightly better.虽然两个示例都可以改进,但我认为实现 1 稍微好一些。 In both cases you do dynamic casting.在这两种情况下,您都进行动态转换。 However, in Implementation 1, you do an implicit upcasting in "Emp = Mng;", while in Implementation 2 you do downcasting in "Manager Mng = (Manager )Emp;".但是,在实现 1 中,您在“Emp = Mng;”中进行了隐式向上转换,而在实现 2 中,您在“Manager Mng = (Manager )Emp;”中进行了向下转换。

In general you should avoid casting (especially the downcasting since it's not that safe all the time compared with upcasting), and if you have to you should use C++ style casting (eg dynamic_cast).一般来说,您应该避免强制转换(尤其是向下转换,因为与向上转换相比,它在所有时间都不是那么安全),如果必须,您应该使用 C++ 风格的强制转换(例如 dynamic_cast)。 See the example inhttps://www.tutorialcup.com/cplusplus/upcasting-downcasting.htm请参阅https://www.tutorialcup.com/cplusplus/upcasting-downcasting.htm 中的示例

A better solution is to use virtual functions in order to avoid casting and make room to add more objects types beside "Manager".更好的解决方案是使用虚拟函数以避免强制转换并腾出空间在“管理器”旁边添加更多对象类型。 For example, your header may look like:例如,您的标题可能如下所示:

class Employee
{
  public:
    virtual void setDesignation(const string & d) = 0;
    virtual string getDesignation() = 0; 
};

class Manager : public Employee
{
  public:
    virtual void setDesignation (const string & d) {Designation=d;}
    virtual string getDesignation() {return Designation;}

  private:
    string Designation;
};

and your function may look like:您的函数可能如下所示:

Employee* SomeFunction(bool SomeCondition)
{
   Employee *Emp = NULL;
   if (SomeCondition) 
   {
     Emp = new Manager;;
     Emp->setDesignation("BOSS");             
   }              
   return Emp;
}

then if you want to access the Designation later, you can do那么如果你想稍后访问指定,你可以这样做

cout << SomeFunction(true)->getDesignation();

** About Polymorphism ** 关于多态

you don't use any Polymorphism in both examples.在这两个示例中您都没有使用任何多态性。 This is becuase you don't use any function that is type-specific, and so your runtime behaviour doesn't vary depending on the "Employee" object (you are merely using one object type "Manager" anyways !).这是因为您不使用任何特定于类型的函数,因此您的运行时行为不会因“员工”对象而异(无论如何您只是使用一种对象类型“经理”!)。 See the example in http://www.tutorialspoint.com/cplusplus/cpp_polymorphism.htm请参阅http://www.tutorialspoint.com/cplusplus/cpp_polymorphism.htm 中的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM