2010-05-11 59 views
0

我有点糊涂:C++键入和OOP子类

  • 如果我有一个基类A,并且其延伸的一个类B,可以在类型A的变量保持的值B型,反之亦然?

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

  • 如果这是可能的,当我使用这个时需要注意什么? 这将如何解决性能方面的问题?

注:对不起,如果我问太多问题,不理会他们,只是看出来的那些名单装饰点“标记” :) 而且,这也不是我的功课。我是一名业余爱好程序员,拥有使用OOP编写脚本语言的技能,但对于使用C++进行OOP打字的人来说,我还是比较陌生。

+0

也许提供一些代码作为例子:) – 2010-05-11 20:58:20

+1

为什么?我现在没有任何具体的例子。子类与“父类相同”的规则应该是一般的,或者? – Zack 2010-05-11 20:59:55

+0

没有具体的例子就是为什么你感到困惑。对代码进行编码,它会帮助你全力以赴。 – jmucchiello 2010-05-11 21:27:01

回答

3

如果你这样做:

B b; 
A a = b; 

那么你得到 “切片”。 a将只包含bA部分。

但你可以有引用/指针:

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

在这种情况下,rapa只是指/点到真正B对象。这是因为公共继承建模了一个IS-A关系。使用更多的描述性名称更容易理解。可以考虑AAnimalB作为Baboon。 A Baboon IS-A Animal所以通过使用引用/指针,您可以将它视为Baboon,因为它是更通用的Animal类型。

+0

你能解释一下为什么这个指针可以工作吗?为什么C++不会出现输入错误?我的意思是A!= B,或? – Zack 2010-05-11 21:02:26

+1

'A'和'B'是类型,而不是对象(与许多其他类型为对象的语言不同)。使用指针,'A *'可以指代从A派生的任何东西,并且虚函数将被正确地转发给派生类的实现。例如。 '动物*动物=新狒狒();动物 - >吃();动物 - >睡眠();如果它们是虚拟的(在动物中)并且在狒狒中被覆盖,则会调用狒狒类的饮食和睡眠方法。 OTOH,如果你做了'动物a =狒狒'()',一个狒狒会被创造出来,但是然后*切片*,你将剩下一个有效的动物,它不包含任何额外的狒狒。 – 2010-05-11 21:10:16

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)必须在运行时发生 - 这是称为动态调度。与非虚拟方法的决定可以在编译时

+1

在C++中,您分配给的变量需要是一个引用(您的代码将被编译,但它不会像您期望的那样运行)。代码应该是'Cat c;动物&a = c;'和'动物a;猫&c = a;'。查看其他答案。 – 2010-05-11 21:14:42

+0

这可能是合法的,但它不是非常有用。正如Ken所说,使用引用(或指针)。 – jmucchiello 2010-05-11 21:25:45

0

指针参考碰巧A类的对象可以指向/参考B类的对象。那是因为如果B派生自A,那么B是-aAB类的每个对象都具有类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! 

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

0

不是相反的,但表现并不是正确的问题。如果你已经决定要做一个面向对象的设计,不要为牺牲性能问题而牺牲正确的抽象。不成熟的优化是万恶之源。祝你好运!