交叉引用的解决方法-类方法的应用
来源:互联网 发布:中科大linux内核分析 编辑:程序博客网 时间:2024/06/03 17:19
什么是交叉引用?一言以蔽之,就是:A类中包含B类的对象,B类中包含A类的对象。
以一场景为例
我们先来看一个场景。假设有一个电子文档(Document)、一个文档下有多个页(Page),每个页下有多个文本单元(TextUnit,表示文档内元素的基本单位),一个文档中的所有文本单元对象都有唯一的ID。这样每创建一个文本单元时都要为其设置一个唯一的ID,我们在Document类中就需要一个生成唯一ID的方法为所有的文本单元创建唯一标识。于是我们就会有下面的类关系设计图:
于是我们想当然的会有这样的代码:
TextUnit.h:
#pragma once
class TextUnit
{
public:
TextUnit(void);
TextUnit(int id);
~TextUnit(void);
public:
int GetId() { return m_id; }
void SetId(int id) { m_id = id; }
private:
int m_id; //文本对象的唯一标识
};
TextUnit.cpp:
#include "StdAfx.h"
#include "TextUnit.h"
TextUnit::TextUnit(void)
{
}
TextUnit::TextUnit( int id ) : m_id(id)
{
}
TextUnit::~TextUnit(void)
{
}
Page.h:
#pragma once
#include <vector>
#include "TextUnit.h"
#include "Document.h"
typedef std::vector<TextUnit*> VecTextUnit;
class Page
{
public:
Page(Document* pDocument);
~Page(void);
public:
//添加一个文本单元
TextUnit* AddTextUnit();
private:
Document* m_pDocument; //文档对象,用于获得ID
VecTextUnit* m_pvecTextUnits; //文本单元对象
};
Page.cpp:
#include "StdAfx.h"
#include "Page.h"
Page::Page(Document* pDocument) : m_pDocument(pDocument), m_pvecTextUnits(new VecTextUnit)
{
}
Page::~Page(void)
{
for (VecTextUnit::iterator iter = m_pvecTextUnits->begin(); iter != m_pvecTextUnits->end(); ++ iter )
{
delete[] *iter;
*iter = NULL;
}
m_pvecTextUnits->clear();
delete[] m_pvecTextUnits;
m_pvecTextUnits = NULL;
}
TextUnit* Page::AddTextUnit()
{
int id = m_pDocument->GenerateId();
TextUnit* pTextUnit = new TextUnit(id);
if (pTextUnit == NULL)
{
return NULL;
}
m_pvecTextUnits->push_back(pTextUnit);
return pTextUnit;
}
Document.h:
#pragma once
#include <vector>
#include "Page.h"
typedef std::vector<Page*> VecPage;
class Document
{
public:
Document(void);
~Document(void);
public:
//生成本文档内唯一的文本对象ID
int GenerateId();
//添加一页
Page* AddPage();
private:
static int s_id; //用于生成唯一的ID
VecPage* m_pvecPages; //所有的页
};
Document.cpp:
#include "StdAfx.h"
#include "Document.h"
int Document::s_id = 0;
Document::Document(void) : m_pvecPages(new VecPage)
{
}
Document::~Document(void)
{
for (VecPage::iterator iter = m_pvecPages->begin(); iter != m_pvecPages->end(); ++ iter )
{
delete[] *iter;
*iter = NULL;
}
m_pvecPages->clear();
delete[] m_pvecPages;
m_pvecPages = NULL;
}
int Document::GenerateId()
{
return s_id ++;
}
Page* Document::AddPage()
{
Page* pPage = new Page(this);
if (pPage == NULL)
{
return NULL;
}
m_pvecPages->push_back(pPage);
return pPage;
}
编译
好,代码写完了,我们对它进行编译,这时你会发现一堆的错误:
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\document.h(6): error C2065: ‘Page’ : undeclared identifier
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\document.h(6): error C2059: syntax error : ‘>’
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\document.h(9): error C2143: syntax error : missing ‘;’ before ‘{’
…
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\page.h(12): error C2061: syntax error : identifier ‘Document’
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\page.h(20): error C2143: syntax error : missing ‘;’ before ‘*’
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\page.h(20): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\博客文章\c++高级编辑\projects\crossreference\crossreference\page.h(20): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
…
原因分析
这是因为
1. C++中,在创建或使用一个类时,这个类必须被定义完整(就是一个完整的类型);
2. 类的定义也可以和函数一样分成两步,先声明后定义。
class T; //声明一个类
这种声明也被称为前向声明,在程序中引入名字T,并指明T是一种类类型。此时的T在它被定义之前是不完整的类型(incomplete type),也就是说只知道它是一种类类型,并不知道它有哪些成员,但可定义这个类型(T)的指针和引用。
类的定义:
class T
{
// todo: 定义类的成员(属性和方法)
};
只有类(T)定义完成,它才是一个完整的类型,才是可见的(才可被创建和使用)。
而我们的程序现在就出现这种很有意思的状态:在定义Document时,发现Page还没有定义完整(Document中有Page类型的成员);在定义Page的时候发现Document还没有定义完整(Page中有Document类型的指针对象)。也就是说Document不知道Page,Page不知道Docunent,这时就像两只狗打架,A狗咬着B狗的尾巴,B狗咬着A狗的尾巴。
解决方法
1.在Document.h文本中加入Page类的声明:calss Page; 把include “Page.h”放到Document.cpp中。
2.Page.h文本中加入Page类的声明:calss Document; 把include “Document.h”放到Page.h中。
代码如下:
#pragma once
#include <vector>
class Page;
typedef std::vector<Page*> VecPage;
class Document
{
public:
Document(void);
~Document(void);
public:
//生成本文档内唯一的文本对象ID
int GenerateId();
//添加一页
Page* AddPage();
private:
static int s_id; //用于生成唯一的ID
VecPage* m_pvecPages; //所有的页
};
Document.cpp:
#include "StdAfx.h"
#include "Document.h"
#include "Page.h"
int Document::s_id = 0;
Document::Document(void) : m_pvecPages(new VecPage)
{
}
Document::~Document(void)
{
for (VecPage::iterator iter = m_pvecPages->begin(); iter != m_pvecPages->end(); ++ iter )
{
delete[] *iter;
*iter = NULL;
}
m_pvecPages->clear();
delete[] m_pvecPages;
m_pvecPages = NULL;
}
int Document::GenerateId()
{
return s_id ++;
}
Page* Document::AddPage()
{
Page* pPage = new Page(this);
if (pPage == NULL)
{
return NULL;
}
m_pvecPages->push_back(pPage);
return pPage;
}
Page.h:
#pragma once
#include <vector>
#include "TextUnit.h"
class Document;
typedef std::vector<TextUnit*> VecTextUnit;
class Page
{
public:
Page(Document* pDocument);
~Page(void);
public:
//添加一个文本单元
TextUnit* AddTextUnit();
private:
Document* m_pDocument; //文档对象,用于获得ID
VecTextUnit* m_pvecTextUnits; //文本单元对象
};
Page.cpp:
#include "StdAfx.h"
#include "Page.h"
#include "Document.h"
Page::Page(Document* pDocument) : m_pDocument(pDocument), m_pvecTextUnits(new VecTextUnit)
{
}
Page::~Page(void)
{
for (VecTextUnit::iterator iter = m_pvecTextUnits->begin(); iter != m_pvecTextUnits->end(); ++ iter )
{
delete[] *iter;
*iter = NULL;
}
m_pvecTextUnits->clear();
delete[] m_pvecTextUnits;
m_pvecTextUnits = NULL;
}
TextUnit* Page::AddTextUnit()
{
int id = m_pDocument->GenerateId();
TextUnit* pTextUnit = new TextUnit(id);
if (pTextUnit == NULL)
{
return NULL;
}
m_pvecTextUnits->push_back(pTextUnit);
return pTextUnit;
}
- 交叉引用的解决方法-类方法的应用
- 交叉引用的解决方法——类声明的应用
- 交叉引用的解决方法——类声明的应用
- 智能指针的交叉引用问题及解决方法
- C++类的交叉引用问题
- Word 2013 参考文献插入及交叉引用的实现方法
- 非Activity类引用getResources()方法问题的解决方法
- 非Activity类引用getResources()方法问题的解决方法
- 非Activity类引用getResources()方法问题的解决方法
- 非Activity类引用getResources()方法问题的解决方法
- 文件的交叉引用辅助工具
- 智能指针的交叉引用
- 样式的交叉应用
- 《ios_oc》重复引用、交叉引用、可见度、方法,setter、getter、自定义初始化init的修改
- 两个C++类的交叉引用和同步改变
- c++23、C++中类的交叉引用
- 类的交叉引用(或头文件依赖与交叉包含)
- Python模块的交叉引用问题
- 深度学习方向的牛人个人主页,文章必须带代码呀,持续更新
- C语言关键字解析(一)
- c# 换行符
- 欢迎使用CSDN-markdown编辑器
- OpenGL ES(2)——定义图形
- 交叉引用的解决方法-类方法的应用
- leetcode-Longest Increasing Subsequence
- 程序员到底是怎么来的?
- iOS生成随机数
- 集合分割
- java反射
- IIS支持mp4等视频播放的设置
- J-Link clone问题
- apps被拒绝的各种理由