掉坑了..原来的代码在vs2019中 编译不通过

lunatic7 2020-10-12 03:27:30

class A
{
public:
A(){}
virtual ~A(){ TRACE("3\r\n"); }


virtual BOOL Create(DWORD a) {
TRACE("2\r\n");
return TRUE; }
};


class B : public A
{
public:
B() {}
virtual ~B() { TRACE("4\r\n"); }


BOOL Create(DWORD a, DWORD b, int c) {
TRACE("1\r\n");
return true;
}
};


A* p = new B;//这个地方不会自动转换类型了 ((B*)p)->Create(1, 2, 3);
p->Create(1, 2, 3);




已经在使用的代码..掉坑了这下 VS2019 16.7.3
是不是有啥新的转换方法
...全文
994 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lunatic7 2020-10-14
  • 打赏
  • 举报
回复
引用 10 楼 真相重于对错 的回复:
无论vs2010还是vs2015都不能通过编译,程序代码往往是差之毫厘,失之千里。如果你的项目可以通过编译,自己好好看看,它肯定不是和你说的那样。
好的 谢谢 谢谢!非常感谢 我现在3端搞 再加上维护这破玩意 等有时间再具体研究 应该是我哪里搞错了 但是他这是商业代码十多年的项目了 我以为是我理解的问题
真相重于对错 2020-10-13
  • 打赏
  • 举报
回复
无论vs2010还是vs2015都不能通过编译,程序代码往往是差之毫厘,失之千里。如果你的项目可以通过编译,自己好好看看,它肯定不是和你说的那样。
真相重于对错 2020-10-13
  • 打赏
  • 举报
回复
引用 7 楼 lunatic7 的回复:
[quote=引用 5 楼 真相重于对错 的回复:]vs2013 可以这样吗?
这都是08年左右的商业代码结构 到现在一直在生产的呢 在vs2019 16.7 以前的版本都可以 vs2015我也试过 但是我现在总不能把代码重新搞成以前的版本吧 我也是没事没找 vs2019唯一的优点就是编译的体积小 就看准了他这点好处 16.7之后的麻烦事太多了 [/quote] 你肯定看漏了什么东西,你所例举的代码,语法根本就是错误的。自己再好好查一下吧
lunatic7 2020-10-13
  • 打赏
  • 举报
回复
我在A类里有一个函数 比如 static A* Test(int nType){ A* Ret = NULL; switch (nType) { case 0: Ret = new B; case 1: Ret = new C; default: break; } return A; } 大体是这么个意思 所以他现在给我造成的困扰 等于是要修改全部代码 要不用强制指定类型 (B*)P 这样 要不直接 B* p=new B 或者修改解决方案版本。改成以前的 不用vs2019 这样又有新问题 新修改的代码用到了c++14 或者17标准 现在想哭的心都有了
lunatic7 2020-10-13
  • 打赏
  • 举报
回复
引用 5 楼 真相重于对错 的回复:
vs2013 可以这样吗?
这都是08年左右的商业代码结构 到现在一直在生产的呢 在vs2019 16.7 以前的版本都可以 vs2015我也试过 但是我现在总不能把代码重新搞成以前的版本吧 我也是没事没找 vs2019唯一的优点就是编译的体积小 就看准了他这点好处 16.7之后的麻烦事太多了
schlafenhamster 2020-10-13
  • 打赏
  • 举报
回复
编译器在编译时并不知道要调用的函数体的正确位置,但它插入了一段能找到正确的函数体的代码。这称之为 晚捆绑(late binding) 或 运行时捆绑(runtime binding) 技术。
  通过virtual 关键字创建虚函数能引发晚捆绑,编译器在幕后完成了实现晚捆绑的必要机制。它对每个包含虚函数的类创建一个表(称为VTABLE),用于放置虚函数的地址。在每个包含虚函数的类中,编译器秘密地放置了一个称之为vpointer(缩写为VPTR)的指针,指向这个对象的VTABLE。所以无论这个对象包含一个或是多少虚函数,编译器都只放置一个VPTR即可。VPTR由编译器在构造函数中秘密地插入的代码来完成初始化,指向相应的VTABLE,这样对象就“知道”自己是什么类型了。 VPTR都在对象的相同位置,常常是对象的开头。这样,编译器可以容易地找到对象的VTABLE并获取函数体的地址。
  如果我们用sizeof查看前面Base类的长度,我们就会发现,它的长度不仅仅是一个int的长度,而是增加了刚好是一个void指针的长度(在我的机器里面,一个int占4个字节,一个void指针占4个字节,这样正好类Base的长度为8个字节)。
  每当创建一个包含虚函数的类或从包含虚函数的类派生一个类时,编译器就为这个类创建一个唯一的VTABLE。在VTABLE中,放置了这个类中或是它的基类中所有虚函数的地址,这些虚函数的顺序都是一样的,所以通过偏移量可以容易地找到所需的函数体的地址。假如在派生类中没有对在基类中的某个虚函数进行重写(overriding),那么还使用基类的这个虚函数的地址(正如上面的程序结果所示)。
真相重于对错 2020-10-13
  • 打赏
  • 举报
回复
vs2013 可以这样吗?
lunatic7 2020-10-12
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
class B : public A { virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ; }
这样子我是知道的 还有强制指定类型 ((B*)p)->Create(1,2,3) 这样我框架就没用了 我有很多继承类 参数都不相同的 只有在这个vs2019新版本上 编译不了 老版本都可以正常编译 vs2015 2013一样可以 要是全改 工程量太大了 vs2019的老版本也没法安装 这东西真的草蛋
lunatic7 2020-10-12
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903 的回复:
虚函数 的 参数形式和个数要一样,才能通过基类指针调用 要么参数形式写成一样, 要么明确类型再调用

class A
{
  virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ;
}
class B : public A
{
  virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ;
}
p->Create(1, 2, 3);

或者
((B*)p)->Create(1,2,3)

对 他现在的新版本必须这样 但是在2019 16.7.3以前的就不用 vs2015 vs2013都可以直接调用继承类的Create 我原来的代码已经用于生产了 蛋疼的玩意 现在编译不了 2019还装不了老版本
schlafenhamster 2020-10-12
  • 打赏
  • 举报
回复
class B : public A
{
virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ;
}
zgl7903 2020-10-12
  • 打赏
  • 举报
回复
虚函数 的 参数形式和个数要一样,才能通过基类指针调用 要么参数形式写成一样, 要么明确类型再调用

class A
{
  virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ;
}
class B : public A
{
  virtual BOOL Create(DWORD a, DWORD b=0, int c=0) ;
}
p->Create(1, 2, 3);

或者
((B*)p)->Create(1,2,3)

16,472

社区成员

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

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

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