难道一直是虚函数在作怪!怎样才能安全地向下或向上转型,虚函数对内存布局有什么影响

难道一直是虚函数在作怪!?怎样才能安全地向上或向下转型,虚函数对内存布局有什么影响?GlobelDef.h:#define

难道一直是虚函数在作怪!?怎样才能安全地向上或向下转型,虚函数对内存布局有什么影响?
GlobelDef.h:


#define EMPTY      0
#define WHITEPIECE 1       
#define BLACKPIECE 2
#define WHITETURN  3
#define BLACKTURN  4
#define GAMESTOP   5
#define BLACKWIN   6
#define WHITEWIN   7

#define NULL       0
//工具宏
#define ENSURE_RIGHTPIECE(whosturn) (whosturn-2)
//错误信息定义
#define OK                       0
#define ERR_PIECE_CONFLICT      -1
#define ERR_IGO_CONFLICT        -2
#define ERR_OTHER               -3



#include<iostream>
#include"GlobelDef.h"

using namespace std;

class CCoordinate
{
public:
CCoordinate();
virtual ~CCoordinate();

/*virtual*/ int setState(int pieceType);
//protected:
int mState;    
};


CCoordinate::CCoordinate()
{
mState=EMPTY;
}

CCoordinate::~CCoordinate()
{
}


int CCoordinate::setState(int pieceType)
{
if(mState==EMPTY)
{
mState=pieceType;
return OK;
}
else
return ERR_PIECE_CONFLICT;
}

class CIgoCoordinate:public CCoordinate
{
public:
CIgoCoordinate();
~CIgoCoordinate();
int mLife;
int flag;
//int num;
};

CIgoCoordinate::CIgoCoordinate()
{
mLife=4; 
flag=0;
}

CIgoCoordinate::~CIgoCoordinate()
{

}




int main()
{
CCoordinate** coorList=new CCoordinate*[19];
for (int y=0;y<19;y++)
coorList[y]= new CIgoCoordinate[19];

for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
{
//std::cout<<i<<","<<j<<"state:"
std::cout<<((CIgoCoordinate**)coorList)[i][j].mLife<<" ";  //这里输出的生命值是正常的。但却不能用虚函数setState对基类成员赋值?!
coorList[i][j].setState(1);             //一旦我把这个函数在基类中声明为虚,程序就会崩溃!
if(j==18)
std::cout<<std::endl;
if(j==10)
std::cout<<"|";
}
    std::cout<<"_________________________________________"<<std::endl;
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
{
//std::cout<<i<<","<<j<<"state:"
std::cout<<(coorList)[i][j].mState<<" ";
if(j==18)
std::cout<<std::endl;
}
system("pause");
}


虚函数?内存布局?向上转型
[解决办法]
肯定不行了,coorList的类型是CCoordinate**,如果按下标访问的话,是以CCoordinate的倍数大小进行访问的,然后你的数组确是以CIgoCoordinate的倍数大小来申请的
[解决办法]
 CCoordinate** coorList=new CCoordinate*[19];
    for (int y=0;y<19;y++)
        coorList[y]= new CIgoCoordinate[19];





这个代码看得很头大,而且只有new没有delete , 这里直接老老实实用对象二维数组就可以。
CIgoCoordinate  coorList[19][19] ;



程序崩溃估计是数组越界或野指针
[解决办法]
你是以派生类大小来申请,但是现在的问题是你使用的方式错了,你所想的内存分布跟正确的内存分布不一致,你应该用这样的方式
((CIgoCoordinate**) coorList)[i][j].setState(1); 

[解决办法]
1,向应该上转型安全--- Liskov替换原则
2, 向下转型使用dynamic_cast
3, 你的程序中,有对象切割(object slice), 这是根本的错误。
4,尽量避免显示转型
[解决办法]


std::cout<< coorList[i][j]->getState()<<" ";
if(j==18)
std::cout<<std::endl;
}

    for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
{
delete coorList[i][j];
}
return 0;
}


[解决办法]
引用:
引用:1,向应该上转型安全--- Liskov替换原则
2, 向下转型使用dynamic_cast
3, 你的程序中,有对象切割(object slice), 这是根本的错误。
4,尽量避免显示转型
我是做的向下转型,派生类比基类大,也不该出现对象切割啊?


对象切割不是这个意思。

cordlist类型为T**,cordlist[y] = new SubT[19]; //这里发生了切割, 把19个SubT切成了19个T对象。简单来说cordlist[i][j]的静态/动态类型都是T,而不是T&或T*,所以完全没有动态性。


[解决办法]
做个可能不太恰当的比喻:
人想让狗帮忙逮只兔子,可是人说话狗听不懂,于是人发明了一种介乎人言和狗语之间的语言,即口令。
人想让电脑帮忙做计算,可是人话电脑听不懂,于是人发明了一种介乎人言和汇编机器码之间的语言,即C语言。
人对狗的口令得让人容易学、也得让狗容易懂。
C语言同样得让人容易学、也得让电脑容易懂。
相比之下C++、Java就是人学得费劲、电脑也经常闹不懂。

[解决办法]
CCoordinate* coorList[y]= new CIgoCoordinate[19]; 是不建议的
因为子类和父类内存大小不一定是一样的(大多数情况下是不一样的),
在大小不一样的情况下,CCoordinate+1和CIgoCoordinate+1的内存跨度是不一样的,会导致内存混乱