基类指针可以指向派生类对象。如果没有铸造,为什么反之亦然? 逻辑上,基类没有足够的派生类信息,但派生类也应该具有基类的信息。 我在这里缺少一些基础知识。
答案 0 :(得分:128)
如果我告诉你我有一只狗,你可以放心地假设我有一只宠物。
如果我告诉你我有一只宠物,你不知道这只动物是狗,它可能是一只猫,甚至可能是一只长颈鹿。在不知道一些额外信息的情况下,你无法安全地假设我有一只狗。
类似地,派生对象是基类对象(因为它是子类),因此它可以由基类指针指向。但是,基类对象不是派生类对象,因此无法将其分配给派生类指针。
(你现在听到的吱吱声是类比拉伸)
假设你现在想给我买一件宠物礼物。
在第一种情况下,你知道它是一只狗,你可以给我带一条皮带,每个人都很开心。
在第二种情况下,我没有告诉你我的宠物是什么,所以如果你打算给我买礼物,你需要知道我没有告诉你的信息(或者只是猜测),你给我买了一条皮带如果事实证明我确实有一只狗,每个人都很高兴。
然而,如果我真的有一只猫,那么我们现在知道你做了一个糟糕的假设(演员)并且在皮带上有一个不快乐的猫(运行时错误)。
答案 1 :(得分:11)
我们有两个对象。
class A {
int a;
};
class B : A {
int b;
};
分配B
的实例。我们可以将其与A*
或B*
进行对话。
分配A
的实例。如果我们将其转换为B*
,是否应为成员b
分配空间?
答案 2 :(得分:9)
呃,因为基类不是派生类。
当你有一个指向某个类型的有效指针时,你会说指向的对象在某些位置会有某些数据,以便我们可以找到它。如果你有一个指向派生对象的指针,那么你可以保证指向对象包含所有Derived的数据成员 - 但是当你指向Base时,它实际上没有那个和Bad Things Happen™。 / p>
但是,Derived保证将所有Base数据成员放在相同的位置。这就是为什么指向Base的指针实际上可以指向Derived。
答案 3 :(得分:4)
因为派生类包含基类中的所有内容。但是基类不包括派生类中的所有内容。
建议不要将基类类型转换为派生类:如果尝试访问不属于基类的成员会发生什么?
答案 4 :(得分:3)
这是有效的,因为老虎是动物:
Animal * pAnimal = new Tiger();
这是无效的,因为该物体不是毒镖蛙。
PoisonDartFrog * pPoisonDartFrog = new GenericFrog();
答案 5 :(得分:1)
因为C ++是一种静态类型语言,并且允许隐式的Base-to-Derived转换会破坏类型系统。 Bjarne Stroustrup不希望任何“消息不被理解”的运行时错误。
答案 6 :(得分:1)
class Base
{
public:
int a;
}
class Derived : public Base
{
public:
float b;
}
Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base
// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
// points to the SAME DATA as pBase
答案 7 :(得分:1)
简短答案
class A{
public:
method1();
};
class B: public A{
public:
method2();
};
int main(){
// Case 1
A* ptr_base = new B();
// Here I can call all the methods in A by ptr_base even though it is assigned B ...
// ... because B is derived from A and has all the information about methods of A
// Case 2
B* ptr_derived = new A(); // this will cause error
// Now here ptr_derived is assigned information of A ...
// ... So with this information can I call (*ptr_derived).method2(); ?...
// ... the answer is No because A does not have information of method2() ...;
// ... thus this declaration loses its meaning and hence error.
return 0;
}
答案 8 :(得分:0)
因为基类指针可以指向基类的实例或任何派生类型。派生指针只能指向派生类型或其任何子类。
struct Base {};
struct Derived : Base {};
struct Derived2 : Base {};
Base* p = new Derived(); //Fine, Derived inherits from Base
Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived.
Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived.
就原因而言:一般来说,基指针比派生指针更通用。因此,它对继承类型的了解较少。如果没有强制转换,则无法为派生指针指定基类型的指针,因为它无法判断基指针是派生类型还是其子类型。
答案 9 :(得分:0)
如果将基类指针中的地址分配给派生类指针,则可以将基类对象分配给派生类指针。如果没有派生类,则存在访问派生类成员的风险。派生类方法可以在基类上工作,但只有在方法不访问派生类成员数据时才会这样做。
这是一个巨大的风险。
所以我们强迫你施展,这样你就必须承认所说的免责声明(你可能犯了一个愚蠢的错误,请小心)。
答案 10 :(得分:0)
通常,一种类型的指针不能指向另一种类型的对象。但是,此规则有一个重要例外,该规则仅与您衍生的类相关。 在这种情况下,BASE *类型的指针可能指向Derived类型的对象,即基类指针可以指向派生类对象,但反之亦然,因为基对象不是它的子类对象。
答案 11 :(得分:0)
这是因为“指针的类型是指针指向的对象的类型”。因此,
然后,我们期望在B指向的地址处有一个基本类型的对象(并希望访问其功能),如果在该地址处获得了派生的类型对象,那么我们也可以访问所需的功能。这是因为派生类型是-基本类型。
然后,我们期望在D指向的地址处有一个派生类型对象,如果在那里获得基本类型对象,则由于基本类型不是-派生类型,我们将无法从该基本类型对象访问派生类信息
答案 12 :(得分:0)
行动胜于雄辩。 孩子也可以拥有父类对象。 如果您对指针的理解很好,那么限制就不对了 在下面的代码中,通过子类指针(具有Parent类对象)打印了两个值。 还通过打印证明了自己的地址。 欢迎任何建议!
#include<iostream>
using namespace std;
class Baap{
public:
int a;
void hoo(){ cout<<"hoo\n"; cout<<a;}
};
class Beta:public Baap{
public:
int a;
int b;
void hee(){ cout<<"hee\n"; }
};
int main(){
Baap baap;
baap.a=1;
Beta *beta=(Beta*)&baap;
baap.a=3;
beta->hee();
beta->hoo();
cout<<"\n beta = "<<beta<<"\n&baap = "<<&baap;
return 0;
}
//output
hee
hoo
3
beta = 0x7ffd11dd3834
&baap = 0x7ffd11dd3834