vector存放子类指针的问题

JerryHsiao 2008-05-08 10:15:23
CBase中定义:

typedef vector<CBase*> CBases;
typedef CBases::iterator CBITERATOR;

CBases m_children;

virtual void Read();

构造函数中:

CBase::CBase()
{
CBase *p;
m_children.push_back(p); //应当怎样直接存放子类指针?
}

Read函数实现多态:

void CBase::Read()
{
CBITERATOR ite;

for (ite = m_children.begin(); ite != m_children.end(); ite++)
{
(*ite)->Read(); //这里应该每次取出一个子类指针来调用各自的Read()函数
}
}

派生子类CDerive1,CDerive2:

void CDerive1::Read()
{
AfxMessageBox(_T("CDerive1"));
}
void CDerive2::Read()
{
AfxMessageBox(_T("CDerive2"));
}


我在基类Read函数中可以使用实时赋值的方式实现多态,

*ite = CDerive1;
(*ite)->Read();

这样就又得枚举,然后switch,不方便新加子类,有什么办法让容器中直接放子类指针?或者如何解决?
...全文
262 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhouzhenyan 2008-05-08
  • 打赏
  • 举报
回复
应该这样写:

CBase::CBase(CBase* p)
{
m_children.push_back(p);
}

CDerive1::CDerive1() : CBase(this)
{

}

CDerive1::CDerive2() : CBase(this)
{

}

这样存放到m_children中的就是实际指向各具体派生类对象的指针。
调用时这样写:

CBase *m_pBase;

m_pBase = new CDerive1();
m_pBase->Read(); // 调用CDerive1中实现的Read

m_pBase = new CDerive2();
m_pBase->Read(); // 调用CDerive2中实现的Read
JerryHsiao 2008-05-08
  • 打赏
  • 举报
回复

CBase::CBase()
{
m_children.push_back(this);
AfxMessageBox(_T("CBase"));
}

CDerive1::CDerive1()
{
m_children.push_back(this);
AfxMessageBox(_T("CDerive1")); //没执行到
}

CDerive2::CDerive2()
{
m_children.push_back(this);
AfxMessageBox(_T("CDerive2")); //没执行到
}

在另一个类中调用时:

CBase *m_pBase;
m_pBase = new CBase;
m_pBase->Read()

基类可以构造,子类好像没执行构造,怎么回事?
第二种方法在各自头文件里要将构造函数写成什么形式?暂时编译不过。
yawer 2008-05-08
  • 打赏
  • 举报
回复
第一种方法中,m_children必须是protected属性或者public
CBase::CBase()
{
m_children.push_back(this);
}

CDerive1::CDerive1()
{
m_children.push_back(this);
}

CDerive2::CDerive2()
{
m_children.push_back(this);
}
第二种方法
CBase::CBase(CBase* p)
{
m_children.push_back(p);
}

CDerive1::CDerive1():CBase(this)
{

}

CDerive1::CDerive2():CBase(this)
{

}
个人感觉第2种更好。谢谢!
xjh_net 2008-05-08
  • 打赏
  • 举报
回复
CBase::CBase(CBase* p)
{
m_children.push_back(p); //应当怎样直接存放子类指针?
}

CDerive1::CDerive1():CBase(this)
{

}

CDerive1::CDerive2():CBase(this)
{

}
vcPlayer 2008-05-08
  • 打赏
  • 举报
回复
CBase::CBase()
{
m_children.push_back(this);
}

CDerive1::CDerive1()
{
m_children.push_back(this);
}

CDerive2::CDerive2()
{
m_children.push_back(this);
}
xjh_net 2008-05-08
  • 打赏
  • 举报
回复

/***this is Base.h ***/

#pragma once


#include<vector>
#include <iostream>
using namespace std;


class CBase;
typedef std::vector<CBase*> CBases;
typedef CBases::iterator CBITERATOR;

class CBase
{
//typedef std::vector<CBase*> CBases;
//typedef CBases::iterator CBITERATOR;

static CBases* m_pChildren;

static CBase* _pBase;
public:
CBase(void);
~CBase(void);

CBase(CBase* p)
{
if(NULL==_pBase)
{
_pBase=new CBase;
}

if(NULL==m_pChildren)
{
m_pChildren=new CBases;
}
m_pChildren->push_back(p);
}

virtual void Read()
{
CBITERATOR ite;

for (ite = m_pChildren->begin(); ite != m_pChildren->end(); ite++)
{
(*ite)->Read(); //这里应该每次取出一个子类指针来调用各自的Read()函数
}
}

CBase* getBase()
{
return _pBase;
}
};

//CBases* CBase::m_pChildren=NULL;

class CDerive1: public CBase
{
public:
CDerive1():CBase(this)
{

}
void Read()
{
//AfxMessageBox(_T("CDerive1"));
cout<< "CDerive1";
}
};

class CDerive2: public CBase
{
public:
CDerive2():CBase(this)
{

}
void Read()
{
//AfxMessageBox(_T("CDerive2"));
cout<< "CDerive2";
}
};

/** **/
#include "StdAfx.h"
#include "Base.h"

CBases* CBase::m_pChildren=NULL;

CBase* CBase::_pBase=NULL;
CBase::CBase(void)
{
}

CBase::~CBase(void)
{
}

// TestBase.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "Base.h"
int _tmain(int argc, _TCHAR* argv[])
{

CBase base;
CDerive1 c1;
CDerive2 c2;

c1.Read();
int i=0;
cin>>i;

CBase* p=&c1;
p->Read();

cin>>i;
base.Read();
cin>>i;

CBase* pBase=c1.getBase();
pBase->Read();
return 0;
}

xjh_net 2008-05-08
  • 打赏
  • 举报
回复

/** **/
#include "StdAfx.h"
#include "Base.h"

CBases* CBase::m_pChildren=NULL;//// <-----------
CBase::CBase(void)
{
}

CBase::~CBase(void)
{
}
xjh_net 2008-05-08
  • 打赏
  • 举报
回复
// TestBase.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "Base.h"
int _tmain(int argc, _TCHAR* argv[])
{

CBase base;
CDerive1 c1;
CDerive2 c2;

c1.Read();
int i=0;
cin>>i;

CBase* p=&c1;
p->Read();

cin>>i;
base.Read();
cin>>i;
return 0;
}

xjh_net 2008-05-08
  • 打赏
  • 举报
回复

/***this is Base.h ***/

#pragma once


#include<vector>
#include <iostream>
using namespace std;


class CBase;
typedef std::vector<CBase*> CBases;
typedef CBases::iterator CBITERATOR;

class CBase
{
//typedef std::vector<CBase*> CBases;
//typedef CBases::iterator CBITERATOR;

static CBases* m_pChildren;

public:
CBase(void);
~CBase(void);

CBase(CBase* p)
{
if(NULL==m_pChildren)
{
m_pChildren=new CBases;
}
m_pChildren->push_back(p);
}

virtual void Read()
{
CBITERATOR ite;

for (ite = m_pChildren->begin(); ite != m_pChildren->end(); ite++)
{
(*ite)->Read(); //这里应该每次取出一个子类指针来调用各自的Read()函数
}
}

};

//CBases* CBase::m_pChildren=NULL;

class CDerive1: public CBase
{
public:
CDerive1():CBase(this)
{

}
void Read()
{
//AfxMessageBox(_T("CDerive1"));
cout<< "CDerive1";
}
};

class CDerive2: public CBase
{
public:
CDerive2():CBase(this)
{

}
void Read()
{
//AfxMessageBox(_T("CDerive2"));
cout<< "CDerive2";
}
};
zhouzhenyan 2008-05-08
  • 打赏
  • 举报
回复
基类CBase中的Read()函数实现通用的业务逻辑,而在各派生类中针对具体情况分别实现,并根据设计的情况看是否调用CBase::Read()。如果没有通用的业务逻辑,那么在基类中的Read()中可以不实现。而楼主的代码:

[Quote=引用 11 楼 JerryHsiao 的回复:]
我使用的是虚函数,那么:
void CBase::Read()
{
...
(*ite) = CDerive1; //这句必须有?
(*ite)->Read(); //上面那句没有的话,似乎仍然执行基类Read(),成了无限递归了...
}
[/Quote]
中,在CBase的Read()中不应该调用Read()。
JerryHsiao 2008-05-08
  • 打赏
  • 举报
回复
设计上如何调整?
我想在框架类里调用CBase里的方法,用过虚函数多态性实现多次调用CBase::Read()时分别调用不同子类CDerive里的Read()
JerryHsiao 2008-05-08
  • 打赏
  • 举报
回复
我使用的是虚函数,那么:
void CBase::Read()
{
...
(*ite) = CDerive1; //这句必须有?
(*ite)->Read(); //上面那句没有的话,似乎仍然执行基类Read(),成了无限递归了...
}
zhouzhenyan 2008-05-08
  • 打赏
  • 举报
回复
你用m_pBase = new CBase();当然就是存放指向基类对象的指针,不用
m_pBase = new CDerive1();
m_pBase = new CDerive2();

程序怎么知道你要实例化哪个具体的类呢?
建议设计上做些调整可能会规避你遇到的这个问题。
菜牛 2008-05-08
  • 打赏
  • 举报
回复
你的指针类型是基类并没有关系,虚函数机制可以保证正确的子类功能被调用。虚函数。
JerryHsiao 2008-05-08
  • 打赏
  • 举报
回复
这样用是可以,我的意思是能不能不用
m_pBase = new CDerive1();
m_pBase = new CDerive2();
这样的实时赋值,直接拿出m_chirlren中存放的指针就可以用
目前m_chirlren中存放的仍然是基类指针,我试了很久都无法把子类指针直接存进去
zhouzhenyan 2008-05-08
  • 打赏
  • 举报
回复
不是很明白你的意思,调用子类的什么方法?Read()?如果是调用虚方法,直接这样用就可以了。
JerryHsiao 2008-05-08
  • 打赏
  • 举报
回复
5楼的做法我用过,运行正常,但是这样我每次调用子类方法前都得判断一下需要调用哪个子类,switch...case一下
这样不大方便子类的添加
前面几楼的方法似乎子类构造函数没被执行到,怎么回事?

16,551

社区成员

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

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

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