Nar*_*rek 13 c++ inheritance pointers c++-faq pointer-conversion
我正在读这篇文章,遗憾的是,我无法深入理解为什么编译器不允许从Derived**转换为Base**.此外,我已经看到这个没有提供比parashift.com的链接更多的信息.
编辑:
让我们逐行分析这个代码:
Car car;
Car* carPtr = &car;
Car** carPtrPtr = &carPtr;
//MyComment: Until now there is no problem!
Vehicle** vehiclePtrPtr = carPtrPtr; // This is an error in C++
//MyComment: Here compiler gives me an error! And I try to understand why.
//MyComment: Let us consider that it was allowed. So what?? Let's go ahead!
NuclearSubmarine sub;
NuclearSubmarine* subPtr = ⊂
//MyComment: this two line are OK too!
*vehiclePtrPtr = subPtr;
//MyComment: the important part comes here... *vehiclePtrPtr is a pointer to
//MyComment: a vehicle, particularly in our case it points to a Car object.
//MyComment: Now when I assign to the pointer to the Car object *vehiclePtrPtr,
//MyComment: a pointer to NuclearSubmarine, then it should just point to the
//MyComment: NuclearSubmarine object as it is indeed a pointer to a Vehicle,
//MyComment: isn't it? Where is my fault? Where I am wrong?
// This last line would have caused carPtr to point to sub!
carPtr->openGasCap(); // This might call fireNuclearMissle()!
Run Code Online (Sandbox Code Playgroud)
fre*_*low 20
这与一碗香蕉不是一碗水果的原因基本相同.如果一碗香蕉是一碗水果,你可以把一个苹果放入碗中,它将不再是一碗香蕉.
只要你只检查碗,转换是无害的.但是一旦你开始修改它,转换就变得不安全了.这是要牢记的关键点.(这就是为什么不可变的Scala集合实际允许转换的确切原因,但是可变集合禁止它.)
与你的例子相同.如果有一个转换Derived**为Base**,你可以把一个指针指向一个苹果,类型系统承诺只有指向香蕉的指针可能存在.繁荣!
Dav*_*rtz 11
这样可以避免任何无意义的错误:
class Flutist : public Musician
...
class Pianist : public Musician
...
void VeryBad(Flutist **f, Pianist **p)
{
Musician **m1=f;
Musician **m2=p;
*m1=*m2; // Oh no! **f is supposed to be a Flutist and it's a Pianist!
}
Run Code Online (Sandbox Code Playgroud)
这是一个完整的工作示例:
#include <stdio.h>
class Musician
{
public:
Musician(void) { ; }
virtual void Play(void)=0;
};
class Pianist : public Musician
{
public:
Pianist(void) { ; }
virtual void Play(void) { printf("The piano blares\n"); }
};
class Flutist : public Musician
{
public:
Flutist(void) { ; }
virtual void Play(void) { printf("The flute sounds.\n"); }
};
void VeryBad(Flutist **f, Pianist **p)
{
Musician **m1=f;
Musician **m2=p;
*m1=*m2; // Oh no! **f is supposed to be a Flutist and it's a Pianist!
}
int main(void)
{
Flutist *f=new Flutist();
Pianist *p=new Pianist();
VeryBad(&f, &p);
printf("Mom is asleep, but flute playing wont bother her.\n");
f->Play(); // Since f is a Flutist* this can't possibly play piano, can it?
}
Run Code Online (Sandbox Code Playgroud)
在这里,它正在行动:
$ g++ -fpermissive verybad.cpp -o verybad
verybad.cpp: In function void VeryBad(Flutist**, Pianist**):
verybad.cpp:26:20: warning: invalid conversion from Flutist** to Musician** [-fpermissive]
verybad.cpp:27:20: warning: invalid conversion from Pianist** to Musician** [-fpermissive]
$ ./verybad
Mom is asleep, but flute playing wont bother her.
The piano blares
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1708 次 |
| 最近记录: |