c++类之间相互引用,c++友元类,c++类内互相有对方的指针 KartoSLAM代码为例

9 篇文章 0 订阅
最简单的例子,用A初始化B,用B初始化A

打算用A的m_a变量初始化 B的m_b,以及用B的m_b初始化 m_a. 先将m_a和m_b设置为public,否则不能直接访问别的类的私有成员。
做法:

  1. 声明A class A;
  2. 完成B的函数书写,但是用到A的函数还不能写出函数实体,只能声明。需要在A完成之后再进行函数实体的书写
  3. 完成A的class实现,这里面可以将用到B的函数写出实现过程,因为B已经实现过了。
  4. 将B中用到A的函数实现出来。
#include <iostream>

class A;   //必须要写这个声明,之后再去实现
class B
{
public:
    B():m_b(0){}
    B(A& a);    //这里也只是声明,因为还不知道A的内容,所以在这里不能完成函数的实现

    int m_b;  //这里先设置成 public,否则A不能完成使用m_b来初始化自己
};

class A
{
public:
    A():m_a(0){}
    A(B& b):m_a(b.m_b){}   //

    int m_a;
};
int main()
{
    return 0;
}

B::B(A& a)
{
    m_b = a.m_a;
}
正常情况下A的m_a, B的m_b应该是私有成员,那么就需要借助友元类来完成这个功能。也就是在A里面声明 friend class B。这样B能用A的私有成员。 同时在B的内部声明 friend class A,这样A能用B的私有成员。

代码如下:

#include <iostream>

class A;
class B
{
public:
    B():m_b(0){}
    B(A& a);
    friend class A;
private:
    int m_b;
};

class A
{
public:
    A():m_a(0){}
    A(B& b):m_a(b.m_b){}
    friend class B;
private:
    int m_a;
};

B::B(A& a)
{
    m_b = a.m_a;
}
int main()
{
    return 0;
}
在KartoSLAM 和ORB代码中,还有一些这样的用法:A的成员 有B的指针m_pB,B的成员有A的指针m_pA。

同时希望能够达到这样的效果:以Karto SLAM中的 Mapper、ScanMatcher为例, Mapper的一个指针pMapper和pMapper->m_pSequentialScanMatcher->m_pMapper指向同一个地址。
下面代码是一个简单的描述两个类之间关系的代码

class Mapper
{
public:
	friend class ScanMatcher;
 private:
 	ScanMatcher* m_pSequentialScanMatcher;
}
class ScanMatcher
{
private:
	Mapper* m_pMapper;
}

接下来要如何实现这么一个功能:(由于类内有指针,因此这里还需要写出合适的析构函数)

#include <iostream>
//先写出 MapperGraph和ScanMatcher,这个先写后写和实现函数有关
class Mapper;
class ScanMatcher
{
public:
    //本身ScanMatcher其实是有m_pMapper这个指针的,但是因为m_pMapper很重要,
    //不能在释放ScanMatcher的时候删除m_pMapper。

    //virtual 只是为了给 继承类 重写覆盖用的,在这里不关键
    
    //override 用在子类中,其实没什么大作用,是为了保证被这个关键词修饰的函数是被
    //写成virtual的。加入override可以保证不会因为书写错误而导致编译通过,
    //但实际功能没有达到预期的效果
    virtual ~ScanMatcher(){};  
public:
	static ScanMatcher* Create(Mapper* pMapper);

protected:
	ScanMatcher(Mapper* pMapper):m_pMapper(pMapper){}
private:
	Mapper* m_pMapper;
};

class Mapper
{
	friend class ScanMatcher;
public:
	Mapper();
    ~Mapper()
    {
        delete m_pSequentialScanMatcher;
        m_pSequentialScanMatcher = NULL;
    }
public:
	void Initialize();
private:
	ScanMatcher* m_pSequentialScanMatcher;
};

Mapper::Mapper():m_pSequentialScanMatcher(NULL){}
void Mapper::Initialize()
{
	m_pSequentialScanMatcher = ScanMatcher::Create(this);
}
ScanMatcher* ScanMatcher::Create(Mapper* pMapper)
{
	ScanMatcher* pScanMatcher = new ScanMatcher(pMapper);
	return pScanMatcher;
}

int main()
{
	Mapper* pMapper = new Mapper();
    pMapper->Initialize();
    return 0;
}

这样就完成上面的功能了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值