描述
问题表述比较复杂,得结合代码来表述,代码组成文件如下(见代码一章节):
- D.h,定义了模板函数,定义了一个纯数据类。整个程序的目的就是为了给这个纯数据类提供个性化的处理
- A.h,声明了一个实际上使用纯数据类的业务类A
- A.cpp,为模板函数提供了模板函数内部的具体实现,一个全局的[disPlayMsg]函数。向外围提供了一个业务类A的业务接口,接口内对模板函数进行了实例化。
- B.h,声明了一个实际上使用纯数据类的业务类B
- B.cpp,为模板函数提供了模板函数内部的具体实现,一个全局的[disPlayMsg]函数。向外围提供了一个业务类B的业务接口,接口内对模板函数进行了实例化。
- C.cpp,提供了一个全局函数,用于调用业务类A的业务接口。
- main.cpp,提供main函数,直接调用业务类B的业务接口。通过C.cpp中提供的全局函数间接调用业务类A的业务接口。
实现这段代码的初衷,是为了当外围调用业务类B的业务接口时,能够使用到B.cpp文件中全局函数[B.cpp:disPlayMsg]处理纯数据类对象;当外围调用C.cpp提供的全局函数时,能够访问到业务类A的业务接口,并使用A.cpp文件中的全局函数[A.cpp:disPlayMsg]处理纯数据类对象。
简单的讲就是,当我通过业务A类处理纯数据类对象时,要用[A.cpp:disPlayMsg];当我通过业务类B处理纯数据对象时,要用[B.cpp:disPlayMsg]。(这里解释以下,为什么我不直接对[disPlayMsg]做一个模板函数。在[MSG::printMsg]函数中,不仅仅是简单的调用[disPlayMsg]函数,为了简化问题,我去掉了与问题无关的其他业务逻辑)
实际上程序运行的到的结果如下(见结果章节):
如图所示,问题出现了,在日志[A.cpp:dealMsg begining.]后紧跟的是[This is B.cpp:disPlayMsg.]。
也就是说,当[main]函数通过[C.cpp:dealMsgC]函数访问[A.cpp:CMsgA::dealMsgA]函数时,[A.cpp:CMsgA::dealMsgA]函数内部调用的是[B.cpp:disPlayMsg]函数而不是[A.cpp:disPlayMsg]。
当[main]函数访问[B.cpp:CMsgB::dealMsgB]函数时,[B.cpp:CMsgB::dealMsgB]函数内部调用的是[B.cpp:disPlayMsg]。
(我编译运行了多次,都是同一个结果)。也就是说,因为某些原因,导致了两个在不同动态库中的全局函数[disPlayMsg],被限定成为只能使用其中一个。后续所有对该全局函数的调用,都只能使用这一个函数。这是我的第一个问题,为什么会产生这种现象?
虽然问题已经出现了,但我的重心还是放在如何实现两个业务类能够正确的访问处理纯数据类的函数。
我猜想问题是出现在作用域上,在模板函数中对处理纯数据类的函数调用,可以认为是调用了无名命名空间中的[::disPlayMsg]函数。所以,我修改了模板函数,再增加一个类型,用于指定是哪个业务类发起的调用,然后使用调用者的[disPlayMsg]函数。
代码见代码二章节。
运行结果达到了预期。但是这种解决方式代价有点大,我得修改所有业务代码中对模板函数的调用,为他们添加一个参数。所以我不认为是个好的解决方案。如果有好的解决方案,请在评论中留言,谢谢!
结果一
main begining
This is C.cpp:dealMsg.
A.cpp:dealMsg begining.
This is B.cpp:disPlayMsg.
iNum:1, strMsg:Hello word.
A.cpp:dealMsg ending.
B.cpp:dealMsg begining.
This is B.cpp:disPlayMsg.
iNum:1, strMsg:Hello word!
B.cpp:dealMsg ending.
main ending.
代码一
/***********D.h***********/
#ifndef _D_H_
#define _D_H_
#include <iostream>
class CMsg{
public:
std::string strMsg;
};
namespace MSG{
template <typename typeOne>
void printMsg(int iNum, typeOne strMsg)
{
disPlayMsg(iNum, strMsg);
return;
}
};
#endif
/***********A.h***********/
#define _A_H_
#include <string>
#include "D.h"
class CMsgA{
public:
void dealMsgA(int iNum, std::string strMsg);
};
#endif
/***********A.cpp***********/
#include <iostream>
#include "A.h"
//#include "D.h"
void disPlayMsg(int iNum, CMsg cMsg)
{
std::cout << "This is A.cpp:disPlayMsg." << std::endl;
std::cout << "iNum:" << iNum << ", strMsg:" << cMsg.strMsg << std::endl;
return;
}
void CMsgA::dealMsgA(int iNum, std::string strMsg)
{
std::cout << "A.cpp:dealMsg begining." << std::endl;
CMsg cMsg;
cMsg.strMsg = strMsg;
MSG::printMsg(iNum, cMsg);
std::cout << "A.cpp:dealMsg ending." << std::endl;
return;
}
/***********B.h***********/
#ifndef _B_H_
#define _B_H_
#include <string>
#include "D.h"
class CMsgB{
public:
void dealMsgB(int iNum, std::string strMsg);
};
#endif
/***********B.cpp***********/
#include <iostream>
#include "B.h"
//#include "D.h"
void disPlayMsg(int iNum, CMsg cMsg)
{
std::cout << "This is B.cpp:disPlayMsg." << std::endl;
std::cout << "iNum:" << iNum << ", strMsg:" << cMsg.strMsg << std::endl;
return;
}
void CMsgB::dealMsgB(int iNum, std::string strMsg)
{
std::cout << "B.cpp:dealMsg begining." << std::endl;
CMsg cMsg;
cMsg.strMsg = strMsg;
MSG::printMsg(iNum, cMsg);
std::cout << "B.cpp:dealMsg ending." << std::endl;
return;
}
/***********C.cpp***********/
#include <string>
#include "A.h"
void dealMsgC()
{
std::cout << "This is C.cpp:dealMsg." << std::endl;
CMsgA cMsgA;
int iNum = 1;
std::string strMsg = "Hello word.";
cMsgA.dealMsgA(iNum, strMsg);
return;
}
/***********main.cpp***********/
#include <string>
#include "B.h"
void dealMsgC();
int main(int argc, char* argv[])
{
std::cout << "main begining" << std::endl;
dealMsgC();
CMsgB cMsgB;
int iNum = 1;
std::string strMsg = "Hello word!";
cMsgB.dealMsgB(iNum, strMsg);
std::cout << "main ending." << std::endl;
return 0;
}
/***********Makefile***********/
all:libsameA.so libsameB.so libsameC.so sameFun
libsameA.so:A.o
g++ -shared -o libsameA.so A.o
A.o:A.cpp
g++ -c -fPIC A.cpp
libsameB.so:B.o
g++ -shared -o libsameB.so B.o
B.o:B.cpp
g++ -c -fPIC B.cpp
libsameC.so:C.o
g++ -shared -o libsameC.so C.o -L. -lsameA
C.o:C.cpp
g++ -c -fPIC C.cpp
sameFun:main.o
g++ -o sameFun main.o -L. -lsameB -lsameC
main.o:main.cpp
g++ -c main.cpp
clean_all:
rm ./*.o ./*.so ./sameFun
结果二
main begining
This is C.cpp:dealMsg.
A.cpp:dealMsg begining.
This is A.cpp:disPlayMsg.
iNum:1, strMsg:Hello word.
A.cpp:dealMsg ending.
B.cpp:dealMsg begining.
This is B.cpp:disPlayMsg.
iNum:1, strMsg:Hello word!
B.cpp:dealMsg ending.
main ending.
代码二
/***********D.h***********/
#ifndef _D_H_
#define _D_H_
#include <iostream>
class CMsg{
public:
std::string strMsg;
};
namespace MSG{
template <typename typeOne, typename typeTwo>
void printMsg(int iNum, typeOne strMsg, typeTwo &caller)
{
caller.disPlayMsg(iNum, strMsg);
return;
}
};
#endif
/***********A.h***********/
#define _A_H_
#include <string>
#include "D.h"
class CMsgA{
public:
void dealMsgA(int iNum, std::string strMsg);
void disPlayMsg(int iNum, CMsg cMsg);
};
#endif
/***********A.cpp***********/
#include <iostream>
#include "A.h"
//#include "D.h"
void disPlayMsg(int iNum, CMsg cMsg)
{
std::cout << "This is A.cpp:disPlayMsg." << std::endl;
std::cout << "iNum:" << iNum << ", strMsg:" << cMsg.strMsg << std::endl;
return;
}
void CMsgA::dealMsgA(int iNum, std::string strMsg)
{
std::cout << "A.cpp:dealMsg begining." << std::endl;
CMsg cMsg;
cMsg.strMsg = strMsg;
MSG::printMsg(iNum, cMsg, *this);
std::cout << "A.cpp:dealMsg ending." << std::endl;
return;
}
/***********B.h***********/
#ifndef _B_H_
#define _B_H_
#include <string>
#include "D.h"
class CMsgB{
public:
void dealMsgB(int iNum, std::string strMsg);
void disPlayMsg(int iNum, CMsg cMsg);
};
#endif
/***********B.cpp***********/
#include <iostream>
#include "B.h"
//#include "D.h"
void disPlayMsg(int iNum, CMsg cMsg)
{
std::cout << "This is B.cpp:disPlayMsg." << std::endl;
std::cout << "iNum:" << iNum << ", strMsg:" << cMsg.strMsg << std::endl;
return;
}
void CMsgB::dealMsgB(int iNum, std::string strMsg)
{
std::cout << "B.cpp:dealMsg begining." << std::endl;
CMsg cMsg;
cMsg.strMsg = strMsg;
MSG::printMsg(iNum, cMsg, *this);
std::cout << "B.cpp:dealMsg ending." << std::endl;
return;
}
/***********C.cpp***********/
#include <string>
#include "A.h"
void dealMsgC()
{
std::cout << "This is C.cpp:dealMsg." << std::endl;
CMsgA cMsgA;
int iNum = 1;
std::string strMsg = "Hello word.";
cMsgA.dealMsgA(iNum, strMsg);
return;
}
/***********main.cpp***********/
#include <string>
#include "B.h"
void dealMsgC();
int main(int argc, char* argv[])
{
std::cout << "main begining" << std::endl;
dealMsgC();
CMsgB cMsgB;
int iNum = 1;
std::string strMsg = "Hello word!";
cMsgB.dealMsgB(iNum, strMsg);
std::cout << "main ending." << std::endl;
return 0;
}
/***********Makefile***********/
all:libsameA.so libsameB.so libsameC.so sameFun
libsameA.so:A.o
g++ -shared -o libsameA.so A.o
A.o:A.cpp
g++ -c -fPIC A.cpp
libsameB.so:B.o
g++ -shared -o libsameB.so B.o
B.o:B.cpp
g++ -c -fPIC B.cpp
libsameC.so:C.o
g++ -shared -o libsameC.so C.o -L. -lsameA
C.o:C.cpp
g++ -c -fPIC C.cpp
sameFun:main.o
g++ -o sameFun main.o -L. -lsameB -lsameC
main.o:main.cpp
g++ -c main.cpp
clean_all:
rm ./*.o ./*.so ./sameFun