0

我有点困惑:

  • 如果我有一个基类 A 和一个扩展 A 的类 B,A 类型的变量可以保存 B 类型的值,反之亦然?

如果是,为什么?即使 B 从 A 派生,它们不是完全不同吗?类型安全性如何?

  • 如果这是可能的,我在使用它时需要注意什么?这在性能方面将如何发挥作用?

注意:对不起,如果我问了太多问题,请忽略它们,并注意那些带有列表装饰点的“标记”:) 另外,这不是我的作业。我是一名业余程序员,并且具有使用 OOP 编写脚本语言的技能,但我对 C++ 中的 OOP 输入相对较新。

4

4 回答 4

3

如果你这样做:

B b;
A a = b;

然后你得到“切片”。 a将只A包含b.

但是你可以有参考/指针:

B b;
A &ra = b;
A *pa = &b;

在这种情况下,ra只需pa引用/指向真实B对象。这是因为公共继承对 IS-A 关系建模。使用更具描述性的名称更容易理解。把A和想AnimalB。IS-ABaboon因此通过使用引用/指针,您可以将 a视为更通用的类型。BaboonAnimalBaboonAnimal

于 2010-05-11T20:59:12.093 回答
0

并非相反,但性能在这里不是正确的问题。如果您决定要进行 OO 设计,请不要为了性能问题而牺牲正确的抽象。过早的优化是万恶之源。祝你好运!

于 2010-05-11T21:19:57.900 回答
0

A 类型的变量可以保存 B 类型的值(对于“持有”的某些定义,正如其他答案所解释的那样),但反之亦然。打破一个标准的例子:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};

这是合法的,因为Cat源自Animal

Cat c;
Animal& a = c;

这不是:

Animal a;
Cat& c = a;

这是类型安全的,因为您已将其定义为这样;继承的全部意义在于允许这种事情发生,因此您可以继续调用泛型Animal变量上的方法,而无需知道其中存储了哪个基类。至于性能问题,调用虚方法比较慢,因为必须在运行时决定实际调用哪个方法(Cat::foo()与 相比Dog::foo(),例如,取决于Animal存储在变量中的特定类型)——这称为动态调度. 对于非虚拟方法,决策可以在编译时发生

于 2010-05-11T21:00:23.883 回答
0

指向类对象的指针引用可以A指向/引用类对象B。那是因为如果B派生自A,则 a B is-a A。类的每个对象都具有类B的所有成员变量和函数A,以及类独有的那些B

class A
{
   public:
      virtual ~A();
      void foo();
};

class B : public A
{
   public:
      void bar();
};

A * a = new B;
a->foo(); // perfectly valid, B inherits foo() from A
//a->bar(); // compile-time error, bar() is only defined in B
delete a; // make sure A has a virtual destructor!

通常,当您想通过虚函数利用多态行为时,会使用这种代码。

于 2010-05-11T21:02:29.370 回答