多态性与DownCasting
Polymorphism vs DownCasting
假设我有一个基类Employee
和一个派生类Manager
,如下所示:
class Employee
{
public:
string Name;
};
class Manager : public Employee
{
public:
string Designation;
};
在实现以下功能时:
Employee* SomeFunction(bool SomeCondition)
{
Employee *Emp = NULL;
if (SomeCondition)
{
//Code goes here : Both Implementation 1 and 2 work fine!
}
return Emp;
}
当SomeCondition
为true时,我希望返回一个类型为Manager
的非null对象。在这种情况下,以下两段代码似乎都符合要求:
实施1:
Manager *Mng = new Manager;
Mng->Name = "Adam";
Mng->Designation = "BOSS";
Emp = Mng;
实施2:
Emp = new Manager;
Manager *Mng = (Manager*)Emp;
Mng->Name = "Adam";
Mng->Designation = "BOSS";
既然两者都很好,我想知道两者中哪一个更有效?
哪一个在使用多态性的概念?
实现2中的类型转换是向下转换吗?这是好的做法吗?
虽然我看到了你的问题背后的一些原因,但我认为你需要改进您的示例
-
你是说你需要返回一个非null对象类型为"Manager",而您定义的是"SomeFunction(bool-SomeCondition("返回"雇员"。
-
如果你真的要返回"Employee"对象,为什么要麻烦初始化"指定",而您将无法访问它后来例如:
cout << SomeFunction(true)->Designation(); // error !
所以,我不知道说你的例子很好是什么意思,因为上下文不清楚。
**比较实施1和2/关于动态铸造
虽然这两个例子都可以改进,但我认为Implementation 1较好的在这两种情况下,都执行动态铸造。但是,在实施过程中1,您在"Emp=Mng;"中进行了隐式上转换,而在实现2中您在"ManagerMng=(Manager(Emp;"中执行下转换。
一般来说,你应该避免投射(尤其是向下投射,因为它与upcasting相比,不是一直都那么安全(,如果必须的话您应该使用C++样式的强制转换(例如dynamic_cast(。请参阅中的示例https://www.tutorialcup.com/cplusplus/upcasting-downcasting.htm
更好的解决方案是使用虚拟函数来避免铸造并腾出空间在"管理器"旁边添加更多对象类型。例如,您的标题可能看起来像:
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;
};
你的功能可能看起来像:
Employee* SomeFunction(bool SomeCondition)
{
Employee *Emp = NULL;
if (SomeCondition)
{
Emp = new Manager;;
Emp->setDesignation("BOSS");
}
return Emp;
}
如果你想稍后访问指定,你可以进行
cout << SomeFunction(true)->getDesignation();
**关于多态性
在这两个例子中都没有使用任何多态性。这是因为你没有使用任何特定于类型的函数,这样您的运行时行为就不会根据"Employee"对象的不同而有所不同(您仅使用一种对象类型"经理"!(。请参阅中的示例http://www.tutorialspoint.com/cplusplus/cpp_polymorphism.htm
您的两个实现都按照您的意愿进行,但是第二个实现是非常的糟糕做法。
首先,让我们澄清一下你似乎有一个误解:在你的第二个实现中,你没有做通常被认为是沮丧的事情。您正在使用C样式的强制转换(请参阅http://en.cppreference.com/w/cpp/language/explicit_cast),在丢弃诸如const
之类的东西中,它将愉快地将任何指针丢弃到Manager*
。例如,你还不如做
Manager *Mng = (Manager*) new Employee; // not a good idea
甚至
Manager *Mng = (Manager*) new int; // now, this is really bad...
一般来说,您不应该在C++中使用C样式强制转换。
您可以使用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
尽管如此,检查您的强制转换是否真的安全还是需要运行时开销(即,区分示例中的第一种情况和第二种情况(。顺便说一句,对下变频的需求通常表明设计不好。
简言之,第一个实现是更容易、更明显的方法:不需要向下转换、安全或不安全。
- 多态性和功能结合
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- C++boost序列化多态性问题
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 如何在多线程中正确使用unique_ptr进行多态性?
- 具有智能指针的多态性
- 在 C++ 中在堆栈上创建实例时如何保持多态性?
- 继承/多态性 - 我是否被迫使用"protected"变量?
- C++ 多态性在代码::块 17.12 中不起作用
- C++ 泛型和多态性:这种模式可行吗?
- 为什么我们实际上需要运行时多态性?
- 如何在这个简单的最小示例中实现多态性?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 无法初始化已知大小的矢量指针,该大小不会因多态性而更改
- 运行时多态性和dynamic_cast需要澄清
- 如何调用指针类型的方法(禁用多态性)?
- 从基类调用函数的多态性
- 运行时多态性 - 箭头运算符访问了错误的成员?
- 多态性与DownCasting