2010-08-22 112 views
11

(原谅提前noob问题)C++:多重继承与多态性

我有4类:

class Person {}; 
class Student : public Person {}; 
class Employee : public Person {}; 
class StudentEmployee : public Student, public Employee {}; 

本质Person是基类,其直接由两者StudentEmployee子类。 StudentEmployee采用多重继承的子类StudentEmployee

Person pat = Person("Pat"); 
Student sam = Student("Sam"); 
Employee em = Employee("Emily"); 
StudentEmployee sen = StudentEmployee("Sienna"); 


Person ppl[3] = {pat, sam, em}; 
//compile time error: ambiguous base class 
//Person ppl[4] = {pat, sam, em, sen}; 

当我使用的Person阵列,基类,我可以把Person和所有它的子类的此阵列内。除了StudentEmployee,给出了歧义基类的原因。

鉴于StudentEmployee保证具有Person的所有方法和属性,因此StudentEmployee被认为是Person的一个子类?

  • 如果是这样,为什么编译器不允许我将一个对象分配给它的超类型的变量?
  • 如果没有,为什么不;那么完成这件事的正确方法是什么?

干杯


编辑:抢先,这个问题是不一样的下面的任一:
polymorphism relates inheritance
Inheritance mucking up polymorphism in C++?

回答

13

StudentEmployee当然是Person的子类。问题是这样的两次:它间接继承Person两次(一次通过Student和一次通过Employee),这就是为什么你得到“不明确的基类”错误。为了确保StudentEmployee既继承Person一次,你必须使用虚拟继承,就像这样:

class Person {}; 
class Student : public virtual Person {}; 
class Employee : public virtual Person {}; 
class StudentEmployee : public Student, public Employee {}; 

这将解决您的错误。

尽管如此,代码还存在另一个大问题,它叫做slicing

当你这样做:

Person ppl[3] = {pat, sam, em}; 

3个Person对象数组将被创建,但这些对象将使用Person类的隐含定义拷贝构造函数复制构造。现在,问题在于数组中的对象将只是Person对象,而不是您希望它们的子类的对象。

要解决这个问题,你将不得不作出一个指针数组来Person对象,像这样:

Person* ppl[] = {new Person("Pat"), new Student("Sam"), 
       new Employee("Emily"), new StudentEmployee("Sienna")}; 

Person* ppl[] = {&pat, &sam, &em, &sen}; 
+0

但是,很明显,像这样调用新内存几乎肯定会导致内存泄漏 – Falmarri 2010-08-22 11:13:00

+1

+1的切片。并且为了防止bguiz不知道,这也可能是Person * ppl [] = {&pat,&sam,&em,&sen }; - 这两个选项的内存管理略有不同。 – Michael 2010-08-22 11:19:57

+0

@Falmarri:为什么?你仍然有指针数组。 – Job 2010-08-22 11:31:21

3

有从对象两个同样可能的路径键入StudentEmployee将是Person

对于StudentEmployee类,您都需要使用关键字virtual。请参阅FAQ 25.8实际上要经过整个部分。

+0

谢谢,那篇文章一针见血的头! – bguiz 2010-08-22 10:48:55