弱智问题!!!

allen_zhaozhencn 2002-10-04 09:11:02
大家看看下面这段程序, 在VC6.0中为何出现错误?
class Weight
{
public:
virtual void test();
};

class SpeicalWeight:public Weight
{
public:
virtual void test();
};

void Weight::test()
{
;
}
void SpeicalWeight::test()
{
;
}
void test_dynamic(SpeicalWeight *p);

int main()
{

Weight *p=new SpeicalWeight;
test_dynamic(dynamic_cast<SpeicalWeight*>(p));//运行时出错如果将其
//dynamic_cast 改成 static_cast 则OK,?????
return 0;

}

void test_dynamic(SpeicalWeight *p)
{
p->test();
}


...全文
77 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
wltsui 2002-10-04
  • 打赏
  • 举报
回复
看看这个:

class B{...};

class D : public B{...};

void f()
{
B* pb=new D;//不清楚但是可行
B* pb2=new B;
D* pd=dynamic_cast<D*>(pb); //可行:pb确实指向一个D
...
D* pd2=dynamic_cast<D*>(pb2); //错误:pb2指向一个B,而不是一个D,pd2==NULL
...
}
caitou123 2002-10-04
  • 打赏
  • 举报
回复
你的代码我试过了,很好啊,要不,把你的编译选项全删掉,把我给你的拷进去试试。
allen_zhaozhencn 2002-10-04
  • 打赏
  • 举报
回复
谢谢各位的精彩发言,但是我上面的代码中使用 dynamic_cast 应该是安全的,为什么执行时老是出错??
wltsui 2002-10-04
  • 打赏
  • 举报
回复
你看看这个地址有详细的:

http://www.lzu.edu.cn/netteach/bcyy/newles/VC/Reference/Course02%5CCourse4.htm
caitou123 2002-10-04
  • 打赏
  • 举报
回复
不是去掉,而是要加上,/GR 启用运行时类型信息 (RTTI)
程序没问题,和编译选项有关。
我的是这样的,(在c/c++项下project _options:)
/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/dos1.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ/GR /c
wltsui 2002-10-04
  • 打赏
  • 举报
回复
static_cast运算符

static_cast(expression)表达式将expression转换到独立地基于表达式中给出的类型type_id类型。没有运行类型检查被执行以确保转换的安全性。

语法

static_cast(expression)

static_cast运算符可被用在例如转换一个基类指针到一个派生类指针的操作,这样的转换不总是安全的,

例如:

class B{...};

class D:public B{...};

void f(B* pb,D* pd)
{
D* pd2=static_cast<D*>(pb); //不安全,pb可能只指向B
B* pb2=static_cast<B*>(pd); //安全转换
...
}
与dynamic_cast相反,在pb的static_cast转换上没有作任何运行检查。由pb指向的对象可能不是D类型的对象,使用*pd2的情况可能是灾难性的。例如,调用一个函数是D类的一个成员但不是B类的,可能导致访问冲突。

dynamic_cast和static_cast运算符可在一个类层次中移动一个指针,但static_cast仅依赖于造型转换语句中提供的信息,因此是不安全的。例如:

class B{...};

class D:public B{...};

void f(B* pb)
{
D* pd1=dynamic_cast<D*>(pb);
D* pd2=static_cast<D*>(pb);
}
如果pb真的指向类型D的一个对象,则pd1和pd2将得到相同的结果。如果pd==0,则它们也将得到相同的结果。

如果pb指向类型B的一个对象,但不是指向完整的D类,则dynamic_cast将足以知道返回0。但是static_cast依赖于程序员的坚持让pb指向类型D的一个对象而且简单地返回那个假定的D对象的指针。

因此,static_cast可以实现相反的隐式转换,在这种情况下,结果是未定义的,留给程序员去确保static_cast转换的结果为安全的。

这些动作还适用于类类型以外的其它类型。例如,static_cast可被用于从int到char的转换。但结果字符可能没有足够的位数保持整个整型值,又一次留给程序员去确保static_cast转换的结果为安全的。

static_cast运算符还可被用于执行任何隐式转换,包括标准转换和用户定义的转换。例如:

typedef unsigned char BYTE

void f()
{
char ch;
int i=65;
float f=2.5;
double db1;
ch=static_cast(i); //从int到char
db1=static_cast(f);//从float到double
...
i=static_cast(ch);
]
static_cast运算符可显式地将一个整型值转换到一个枚举类型。如果整型值未落在枚举值的范围内,枚举结果值是不确定的。

static_cast运算符将一个空指针值转换到目标类型的空指针值。

任何表达式可用static_cast运算符显式地转换到void类型,目标void类型可有选择地包括const、volatile或__unaligned属性。

static_cast运算符不能造型除去const、volatile或_ _unaligned属性。有关除去这些属性的信息参见“const_cast运算符”。

const_cast运算符

const_cast运算符可被用于从一个类中除去const、volatile和_ _unaligned属性。

语法

const_cast(expression)

任何对象类型的指针或一个数据成员的指针可被显式地转换到完全相同的类型,带const,volatile和__unaligned限定符除外。对指针和引用,结果将指向源对象,对数据成员指针结果和数据成员的源(非造型)指针一样指向同一成员。由于依赖于引用对象的类型,通过指针、引用或数据成员指针的求结果的写操作将产生未定义的动作

。const_cast运算符将一个空指针值转换为目标类型的空指针值。

reinterpret_cast运算符

reinterpret_cast运算符允许任何指针被转换到任何其它指针类型,它还允许

任何整型转换到任意指针类型,且反之亦然。滥用reinterpret_cast运算符可轻易导致不安全,除非是所期望的转换是固有的低等级,否则你应使用其它造型运算符之一。

语法

reinterpret_cast(expression)

reinterpret_cast运算符可被用于像char*到int*或One_class*到Unrelated*这种内部的非安全的转换。

reinterpret_cast的结果除了用于造型回到其源类型外,不能安全地用于其它任何情况,其它用法至多也是不可移植的。

reinterpret_cast运算符不能造型除去const、volatile或__unaligned属性,关于除去这些属性的信息参见const_cast运算符。

reinterpret_cast运算符将一个空指针值转换到目标类型的空指针值
wltsui 2002-10-04
  • 打赏
  • 举报
回复
* dynamic_cast 用于多态类型的转换

* static_cast 用于非多态类型的转换

* const_cast 用于除去const,volatile和__unaligned属性

* reinterpret_cast 用于位的简单再解释

wltsui 2002-10-04
  • 打赏
  • 举报
回复
* dynamic_cast 用于多态类型的转换
* static_cast 用于非多态类型的转换
* const_cast 用于除去const,volatile和__unaligned属性
* reinterpret_cast 用于位的简单再解释
使用const_cast和reinterpret_cast作为一种最后的手段,因为这些运算符与旧的造型形式有相同的危险性。但是它们还是有必要用于完全取代旧的造型形式。

dynamic_cast运算符

表达式dynamic_cast(expression)将expression操作数转换为一个type-id类型的对象,type-id必须为以前定义的类类型或“void指针”的一个指针或一个引用。如果type-id是一个指针,则expression的类型必须为一个指针或如果type-id是一个引用,则它为一个l值。

语法

dynamic_cast(expression)

如果type-id是一个指向expression的非模糊可访问的直接或间接基类的指针,则结果是type-id类型的唯一子对象的一个指针,例如:

class B{...};

class C:public B {...};

class D:public C {...};

void f(D* pd)
{
C* pc=dynamic_cast<C*>(pd); //可行:C是一个直接基类,pc指向pd的C子对象
B* pb=dynamic_cast<B*>(pd); //可行:B是一个间接基类,pd指向pd的C子对象
...
}
这种类型转换被称为向上造型,因为它使指针按类层次向上移,从一个派生的类到一个派生源类。向上造型是一种隐式转换。

如果type-id是void*,则执行一种运行检查以确定expression的实际类型,结果是由expression指向的完整对象的一个指针。

例如:

class A{...};

class B{...};

void f()
{
A* pa=new A;
B* pb=new B;
void* pv=dynamic_cast<void*>(pa);
//pv现在指向类型A的一个对象
... pv=dynamic_cast<void*>(pb);
//pv现在指向类型B的一个对象
}
如果type-id不是void*,则执行运行检查去查看由expression指向的对象是否可转换为type-id指向的类型。如果expression的类型是type-id类型的一个基类,则执行运行检查去查看expression是否确实指向type-id类型的一个完整对象,如果是真的,则结果是type-id类型的一个完整对象的指针。

例如:

class B{...};

class D : public B{...};

void f()
{
B* pb=new D;//不清楚但是可行
B* pb2=new B;
D* pd=dynamic_cast<D*>(pb); //可行:pb确实指向一个D
...
D* pd2=dynamic_cast<D*>(pb2); //错误:pb2指向一个B,而不是一个D,pd2==NULL
...
}
这种类型转换被称为向下造型,因为它使指针按类层次向下移,从一个给定类到一个从它派生出的类。

在多重继承的情况下,模糊性的可能性被引入。可虑图4.5中给出的类层次:



类型D的一个对象的指针可被安全地造型到B或C。但是如果D被造型到指向一个A对象,结果将是A的哪个实例呢?这将导致一个模糊造型错误。为了克服这个问题,你可以执行两个非模糊的造型。例如:

void f()
{
D* pd=new D;
A* pa=dynamic_cast<A*>(pd); //错误:模糊的
B* pb=dynamic_cast<B*>(pd); //首行造型到B
A* pa2=dynamic_cast<A*>(pb); //可行:非模糊的
}
当你使用虚拟基类时还会引入更进一步的模糊性。考虑图4.6所示的类层次:



在此层次中,A是一个虚拟基类,关于一个虚拟基类的定义见第9章“派生类”中的“虚拟基类”。给定E类的一个实例及指向A子对象的一个指针,转到指向B的指针的dynamic_cast将因为模糊性而失败。你必须先造型回到完整的E对象,然后沿层次向上,以一种非模糊的方式到达正确的B对象。

考虑图4.7所示的类层次。



给定类型E的一个对象和D子对象的一个指针,从D子对象导航到最左边的A子对象,可有三种转换。你可以执行一个dynamic_cast转换从D指针转到E指针,然后一个转换(为dynamic_cast或隐式转换)从E到B,最后一个隐式转换从B到A。例如:

void f(D* pd)
{
E* pe=dynamic_cast<B*>(pd);
B* pb=pe //向上造型,隐式转换
A* pa=pb; //向上造型,隐式转换
}
dynamic_cast运算符还可以用于执行“跨越造型”。使用相同的类层次,例如可以造型一个指针从B子对象到D子对象,只要完整的对象是E类型的。

考虑跨越造型,确实有可能仅在两步内做转换从D指针到最左边的A子对象的指针。你可以从D到B造型转换,然后一个隐式转换从B到A。例如:

void f(D* pd)
{
B* pb=dynamic_cast<B*>(pd); //跨越造型转换
A* pa=pb;//向上造型,隐式转换
}
一个空指针值被dynamic_cast转换为目标类型的空指针值。

当你使用dynamic_cast(expression)时,如果expression不能被完全地转换到type_id类型,则运行检查会导致造型转换失败。例如:

class A{...};

class B{...};

void f()
{
A* pb=new A;
B* pb=dynamic_cast<B*>(pa); //失败,不安全;B不是从A派生来的
...
}
到指针类型的一个失败的造型转换的值是空指针。到引用类型的失败的造型转换丢弃了一个bad_cast异常。

bad_cast异常

dynamic_cast运算符丢弃了一个bad_cast异常,作为到引用类型的一个失败的

造型的值,bad_cast的接口为:

class bad_cast:public logic
{
public:
bad_cast(const __exString& what_arg): logic(what_ary) {}
void raise() {handle_raise(); throw *this;}
//虚拟的__exString what() const; //继承的
};
static_cast运算符

static_cast(expression)表达式将expression转换到独立地基于表达式中给出的类型type_id类型。没有运行类型检查被执行以确保转换的安全性。

语法

static_cast(expression)

static_cast运算符可被用在例如转换一个基类指针到一个派生类指针的操作,这样的转换不总是安全的,

例如:

class B{...};

class D:public B{...};

void f(B* pb,D* pd)
{
D* pd2=static_cast<D*>(pb); //不安全,pb可能只指向B
B* pb2=static_cast<B*>(pd); //安全转换
...
}
与dynamic_cast相反,在pb的static_cast转换上没有作任何运行检查。由pb指向的对象可能不是D类型的对象,使用*pd2的情况可能是灾难性的。例如,调用一个函数是D类的一个成员但不是B类的,可能导致访问冲突。

dynamic_cast和static_cast运算符可在一个类层次中移动一个指针,但static_cast仅依赖于造型转换语句中提供的信息,因此是不安全的。例如:

class B{...};

class D:public B{...};

void f(B* pb)
{
D* pd1=dynamic_cast<D*>(pb);
D* pd2=static_cast<D*>(pb);
}
如果pb真的指向类型D的一个对象,则pd1和pd2将得到相同的结果。如果pd==0,则它们也将得到相同的结果。

如果pb指向类型B的一个对象,但不是指向完整的D类,则dynamic_cast将足以知道返回0。但是static_cast依赖于程序员的坚持让pb指向类型D的一个对象而且简单地返回那个假定的D对象的指针。

因此,static_cast可以实现相反的隐式转换,在这种情况下,结果是未定义的,留给程序员去确保static_cast转换的结果为安全的。

这些动作还适用于类类型以外的其它类型。例如,static_cast可被用于从int到char的转换。但结果字符可能没有足够的位数保持整个整型值,又一次留给程序员去确保static_cast转换的结果为安全的。

static_cast运算符还可被用于执行任何隐式转换,包括标准转换和用户定义的转换。例如:

typedef unsigned char BYTE

void f()
{
char ch;
int i=65;
float f=2.5;
double db1;
ch=static_cast(i); //从int到char
db1=static_cast(f);//从float到double
...
i=static_cast(ch);
]
static_cast运算符可显式地将一个整型值转换到一个枚举类型。如果整型值未落在枚举值的范围内,枚举结果值是不确定的。

static_cast运算符将一个空指针值转换到目标类型的空指针值。

任何表达式可用static_cast运算符显式地转换到void类型,目标void类型可有选择地包括const、volatile或__unaligned属性。

static_cast运算符不能造型除去const、volatile或_ _unaligned属性。有关除去这些属性的信息参见“const_cast运算符”。

const_cast运算符

const_cast运算符可被用于从一个类中除去const、volatile和_ _unaligned属性。

语法

const_cast(expression)

任何对象类型的指针或一个数据成员的指针可被显式地转换到完全相同的类型,带const,volatile和__unaligned限定符除外。对指针和引用,结果将指向源对象,对数据成员指针结果和数据成员的源(非造型)指针一样指向同一成员。由于依赖于引用对象的类型,通过指针、引用或数据成员指针的求结果的写操作将产生未定义的动作

。const_cast运算符将一个空指针值转换为目标类型的空指针值。

reinterpret_cast运算符

reinterpret_cast运算符允许任何指针被转换到任何其它指针类型,它还允许

任何整型转换到任意指针类型,且反之亦然。滥用reinterpret_cast运算符可轻易导致不安全,除非是所期望的转换是固有的低等级,否则你应使用其它造型运算符之一。

语法

reinterpret_cast(expression)

reinterpret_cast运算符可被用于像char*到int*或One_class*到Unrelated*这种内部的非安全的转换。

reinterpret_cast的结果除了用于造型回到其源类型外,不能安全地用于其它任何情况,其它用法至多也是不可移植的。

reinterpret_cast运算符不能造型除去const、volatile或__unaligned属性,关于除去这些属性的信息参见const_cast运算符。

reinterpret_cast运算符将一个空指针值转换到目标类型的空指针值。

运行类型信息

运行类型信息(RTTI)是一种机制,允许对象的类型在程序执行期间被确定。RTTI加到C++语言中,因为很多类库销售者正自己实现这个功能,这导致库之间的不兼容。因此,很明显需要在语言级支持运行类型信息。

为了明确性,RTTI的这个讨论几乎完全限制于指针。但是讨论的概念也适用于引用。

运行类型信息有三个主要的C++语言元素:

* dynamic_cast运算符,用于多态类型的转换。更多的信息参见本章前面部分“dynamic_cast运
allen_zhaozhencn 2002-10-04
  • 打赏
  • 举报
回复
是有这么一句警告,是不是要将编译器参数/GR 去掉呢?
kwiner 2002-10-04
  • 打赏
  • 举报
回复
帮你up一下
wltsui 2002-10-04
  • 打赏
  • 举报
回复
建议你看看 《Effective C++ 2/e 》里面有 类型转换的介绍!
wltsui 2002-10-04
  • 打赏
  • 举报
回复
warning C4541: “dynamic_cast”用在了带 /GR- 的多态类型“Weight”上;可能导致不可预知的行为
连社恐的鸟鸟,现在都变成话痨了…… (这到底是人性的扭曲,还是道德的沦丧) 最近有一种很新的脱口秀:不花钱、一对一、而且任意话题随便and随时聊。 结果一小时跟鸟鸟聊天下来,发现她话多且密,根本就不会把天聊死。 阿里搞出脱口秀版GPT!与鸟鸟激辩一小时,话痨到停不下来。 (这样的语速和情绪,倒是差点被烦死了。) 原来啊,是一个阿里新版本大模型的技术演示脱口秀版GPT——鸟鸟分鸟,并且已经在天猫精灵上为个人终端行业的客户做了演示,量子位抢先体验了一把。 激辩一小时宛如真人面对面,除了社恐这点人设崩塌以外,其他人设倒是屹立不倒: 文本扛把子、有知识有自己的情绪、还能随时来个段子。尤其是在回答弱智问题时,简直被她折服。 这不是脱口秀版GPT,这是科技与狠活呀!哥们! 话不多说,直接上效果。 与弱智吧激辩一小时 鸟鸟分鸟,AKA脱口秀GPT。 作为一名脱口秀演员,鸟鸟最强还是在文本。那就首先来试试强项,结果就是说,任意话题都能展开,甚至还能教你写段子、写作文—— 从开头、场景细节、中心思想细化,最后微调润色等步骤逐步教你入手。 毕竟是文本の神,这些当然不在话下。可以看到,不管是在语速、情绪

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧