Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;类型和OOP子类_C++_Oop_Typing - Fatal编程技术网

C++ C++;类型和OOP子类

C++ C++;类型和OOP子类,c++,oop,typing,C++,Oop,Typing,我有点困惑: 若我有一个基类a和一个扩展了a的类B,a类型的变量是否可以保存B类型的值,反之亦然 若有,原因为何?即使B是从A派生出来的,它们不是完全不同吗?类型安全性如何 如果这是可能的,当我使用它时,我需要注意什么就性能而言,这是如何实现的? 注意:如果我问了太多问题,请不要理会,只需留意那些用列表装饰点“标记”的问题:) 还有,这不是我的家庭作业。我是一个爱好编程的人,有OOP的脚本语言能力,但是我在C++中的OOP打字方面比较新。 B b; A a = b; 然后你得到“切片”

我有点困惑:

  • 若我有一个基类a和一个扩展了a的类B,a类型的变量是否可以保存B类型的值,反之亦然
若有,原因为何?即使B是从A派生出来的,它们不是完全不同吗?类型安全性如何

  • 如果这是可能的,当我使用它时,我需要注意什么就性能而言,这是如何实现的?
注意:如果我问了太多问题,请不要理会,只需留意那些用列表装饰点“标记”的问题:) 还有,这不是我的家庭作业。我是一个爱好编程的人,有OOP的脚本语言能力,但是我在C++中的OOP打字方面比较新。
B b;
A a = b;
然后你得到“切片”<代码>a将只包含
b
a
部分

但您可以使用引用/指针:

B b;
A &ra = b;
A *pa = &b;
在这种情况下,
ra
pa
只需参考/指向真实的
B
对象。这是因为公共继承建立了is-A关系模型。使用更具描述性的名称更容易理解。把
A
Animal
B
想象成
Baboon
狒狒
是一种
动物
,因此通过使用引用/指针,您可以将
狒狒
视为更通用的
动物
类型。

如果您这样做:

B b;
A a = b;
然后你得到“切片”<代码>a将只包含
b
a
部分

但您可以使用引用/指针:

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

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

类型A的变量可以保存类型B的值(对于“hold”的某些定义,如其他答案所解释),但绝对不能反之亦然。要列出一个标准示例,请执行以下操作:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
这是合法的,因为猫源于动物:

Cat c;
Animal& a = c;
这不是:

Animal a;
Cat& c = a;

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

类型A的变量可以保存类型B的值(对于“hold”的某些定义,如其他答案所解释),但绝对不是相反。要列出一个标准示例,请执行以下操作:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
这是合法的,因为猫源于动物:

Cat c;
Animal& a = c;
这不是:

Animal a;
Cat& c = a;
这是类型安全的,因为您已将其定义为类型安全;继承的全部要点是允许这种事情发生,因此您可以继续调用泛型
Animal
变量的方法,而不知道其中存储了什么基类。至于性能问题,调用虚拟方法的速度较慢,因为要决定实际调用哪个方法(
Cat::foo()
Dog::foo()
,例如,取决于变量中存储的
动物的特定类型)必须在运行时发生—这称为动态调度。使用非虚拟方法时,决策可以在编译时进行

指向类
A
的对象的指针或引用可以指向/引用类
B
的对象。这是因为如果
B
来自
A
,那么A
B
就是-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!
通常,当您希望通过虚拟函数利用多态行为时,会使用此类代码。

指向类
A
对象的指针或引用可以指向/引用类
B
对象。这是因为如果
B
来自
A
,那么A
B
就是-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!

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

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

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

或许可以提供一些代码作为示例:)为什么?我现在没有任何具体的例子。孩子们的班级“和”他们的父亲班级“类型相同”的规则应该是一般的,或者?没有具体的例子,这就是为什么你感到困惑的原因。编写一些代码,它将帮助您解决所有问题。也许可以提供一些代码作为示例:)为什么?我现在没有任何具体的例子。子类与父类“具有相同类型”的规则