多态性概念
polymorphism concept
我在运行此程序时遇到"分段错误"。请区分以下两个程序
class xxx{
public: virtual void f(){cout<<"f in xxx"<<endl;} //virtual function
virtual void g(){cout<<"g in xxx"<<endl;} //virtual function
};
class yyy{ //yyy has no relation with xxx at this context
public: virtual void f(){cout<<"f in yyy"<<endl;} //virtual function but no relation with xxx class
void g(){cout<<"g in yyy"<<endl;}
};
int main(int argc, char *argv[])
{
xxx x1,*x;
yyy y1;
x=&x1;
x->f();
x->g();
x=(xxx*) &y1; //one class pointer containing another class object address
x->f();
x->g();
}
-输出
f in xxx
g in xxx
f in yyy
Segmentation fault
但根据多态性概念具有相同的问题
class xxx{
public: virtual void f(){cout<<"f in xxx"<<endl;} //virtual function
virtual void g(){cout<<"g in xxx"<<endl;} //virtual function
};
class yyy:public xxx{ //yyy is derived from xxx
public: virtual void f(){cout<<"f in yyy"<<endl;}
void g(){cout<<"g in yyy"<<endl;}
};
int main(int argc, char *argv[])
{
xxx x1,*x;
yyy y1;
x=&x1;
x->f();
x->g();
x=(xxx*) &y1; //parent class pointer having derived class address
x->f();
x->g();
}
-输出
f in xxx
g in xxx
f in yyy
g in yyy
在第一种情况下,强制转换会产生垃圾,因为您告诉编译器在它没有指向xxx
时&y1
表现得好像它指向了一个。在第二种情况下,yyy
是xxx
,因此将指针投射到yyy
指向xxx
的指针是安全的,因为它是一个。
指针,则可以将其视为指向车辆的指针,因为卡车是车辆。但是,如果你有一个指向一朵花的指针,并将其视为指向车辆的指针,那么它本质上是一个垃圾指针,取消引用它是未定义的行为。
不过,您应该使用C++样式转换而不是 C 样式转换。如果你被迫表达预期的语义,那么更有可能发现这种错误。(编写第一个代码的程序员是否认为它可以作为static_cast
工作?还是他们认为它可以作为reinterpret_cast
?选择一个或在没有铸件的情况下执行操作的额外想法可能会避免错误。
在第一个示例中:
x=(xxx*) &y1; //one class pointer containing another class object address
x->f();
x->g();
变量x
实际上指向与类xxx
无关的类yyy
。事实上,f()
在两者中都声明并且是唯一的虚拟函数,这使得它恰好起作用。由于g()
在类xxx
中是虚函数,但在yyy
中不是虚函数,编译器将生成代码来调用虚函数g()
,其中包含虚函数表中f()
后的任何垃圾(又名vtable
([虚拟函数的具体实现方式当然是一个实现细节, 但是可以公平地期望每个类都有某种函数"表"存储在哪里]。
如果你的yyy
像这样声明,它会给你更有趣的结果:
class yyy{ //yyy has no relation with xxx at this context
public: virtual void g(){cout<<"g in yyy"<<endl;} //virtual function but no relation with xxx class
void f(){cout<<"f in yyy"<<endl;}
};
它会告诉你,由于调用f()
,它必须达到"g in yyy",然后在调用g()
时失败......由于虚函数的工作方式不是根据它们的名称来调用它们,而是根据它们在类中的"顺序"来调用它们[同样,确切的工作方式是一个实现细节,并且由于我们正在处理"未定义的行为",编译器也被允许在屏幕上以闪烁的红色文本打印"答案是42",或者听起来像紧急呼叫中的救护车 - 但这不太可能发生我刚刚在典型的C++编译器实现中描述的]。
在第二种情况下,由于xxx
的virtual
继承到yyy
,函数g()
在yyy
中也是虚拟的,因为"它按照您的预期工作",因为您正在做的事情正是您应该做的。
另请注意,有一些C++样式转换可以帮助您避免犯此类错误 - 如果您做错了,它将在编译时给出错误消息 ( static_cast
(,或者如果您在编译器无法在编译时确定类型的地方使用 dynamic_cast
,它会因此给出nullptr
, 这是一个明显的指标,表明你弄错了。
- 多态性和功能结合
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- C++boost序列化多态性问题
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 如何在多线程中正确使用unique_ptr进行多态性?
- 具有智能指针的多态性
- 在 C++ 中在堆栈上创建实例时如何保持多态性?
- 继承/多态性 - 我是否被迫使用"protected"变量?
- C++ 多态性在代码::块 17.12 中不起作用
- C++ 泛型和多态性:这种模式可行吗?
- 为什么我们实际上需要运行时多态性?
- 如何在这个简单的最小示例中实现多态性?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 无法初始化已知大小的矢量指针,该大小不会因多态性而更改
- 运行时多态性和dynamic_cast需要澄清
- 如何调用指针类型的方法(禁用多态性)?
- 从基类调用函数的多态性
- 运行时多态性 - 箭头运算符访问了错误的成员?
- 为什么我在虚幻引擎中的多态性和接口方面遇到问题?