请教一个跨命名空间 C++拷贝构造函数的问题

2017-05-22 17:27:24 +08:00
 hackpro

中午吃饭组里一个同事问的,折腾的一下午还是没搞定,牛皮吹大了,请教下大家如何解决,谢谢各位

基本需求是两个命名空间存在相同的一个类,TA/TB 以示区别

怎么将命令空间 A 中类 TA 的对象作为命名空间 B 中类 TB 构造函数的参数传入并访问其中的字段?

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

using namespace std;
class B::TB;

namespace A
{
	class TA
	{
	private:
		char *m_pstr;
	public:
		TA(const char *cstr)
		{
			if (cstr == nullptr)
			{
				m_pstr = nullptr;
			}
			else
			{
				int len = strlen(cstr);
				m_pstr = new (nothrow)char[len+1];
				memcpy(m_pstr, cstr, len);
				m_pstr[len] = '\0';
			}
		}

		friend class B::TB;
	};
}

namespace B
{
	class TB
	{
	private:
		char *m_pstr;
	public:
		TB(const char *cstr)
		{
			if (cstr == nullptr)
			{
				m_pstr = nullptr;
			}
			else
			{
				int len = strlen(cstr);
				m_pstr = new (nothrow)char[len+1];
				memcpy(m_pstr, cstr, len);
				m_pstr[len] = '\0';
			}
		}

		//friend class A::TA;
		TB(const A::TA& ta)
		{
			this->m_pstr = ta.m_pstr;
		}
		~TB()
		{
			if (m_pstr != nullptr)
			{
				delete []m_pstr;
				m_pstr = nullptr;
			}
		}
	};
}

int main(int argc, char* argv[])
{
	A::TA a("This is A");
	B::TB b = a;
	return 0;
}
1953 次点击
所在节点    C
12 条回复
Damenly0
2017-05-22 17:46:50 +08:00
using namespace std;
namespace B{
class TB;
}

namespace A
{
xss
2017-05-22 17:57:15 +08:00
用泛型不可以么,? 这样还可以解耦.....
```
template <class TA> class TB {
TB(TA& that){
this.value = that.value;
}
}
```
sfqtsh
2017-05-22 17:58:14 +08:00
luoqeng
2017-05-22 18:07:45 +08:00
TB(const A::TA& ta) {
// this->m_pstr = ta.m_pstr;

if (ta.m_pstr != NULL) {
int len = strlen(ta.m_pstr);
m_pstr = new (nothrow)char[len+1];
memcpy(m_pstr, ta.m_pstr, len);
m_pstr[len] = '\0';
}
}

深拷贝就行了啊
hackpro
2017-05-22 18:49:26 +08:00
@Damenly0 #1 感谢大神,问题出在声明特定命名空间中函数

@xss #2 泛型可以解耦啥意思,可以说具体些吗?

@sfqtsh # 3 感谢提供,清楚地说明白了为啥命名空间中的函数不能直接前置声明

@luoqeng #4 这个是实例代码,这样做的目的就是为了避免深层拷贝
RitchieLee
2017-05-22 18:49:29 +08:00
@sfqtsh 亲测大佬的方法可解决楼主的问题
hackpro
2017-05-22 19:11:16 +08:00
@Damenly0 #1
@xss #2
@sfqtsh #3
@luoqeng #4

请教各位,如果想将权限收紧,只将命名空间中某个类的函数作为友元,即 B::TB::TB(),上面这段怎么继续改?
我尝试了下,没有成功……

namespace A{class TA;}
namespace B{
class TB{
TB(const A::TA& ta);
};
}

namespace A
{
class TA
{
friend B::TB::TB(const TA& ta);
};
}
Damenly0
2017-05-22 19:37:53 +08:00
因为 B::TB::TB()已经涉及到具体 B 的实现,而非声明,考虑到 TB 又依赖于 TA 的实现。如#2 所说,可用 template 解耦
http://stackoverflow.com/questions/10546391/specify-a-class-member-function-as-a-friend-of-another-class
wevsty
2017-05-22 20:25:43 +08:00
为什么不用继承?
xss
2017-05-23 09:51:39 +08:00
或许我写的 template 误导你了. 那个 class TA 实际上应该是 class T.

实际上按照你的需求, TB 是对 TA 是有一定要求的.
一般按照这个尿性发展下去, 你的 TB 一定会对 TA 的要求越来越多. 而一旦 TA 有什么风吹草动, 你就得改一大堆东西.


直接给例子吧:

xss@xss [09:47:01] : ~/Code
$ g++ -c test.cpp -o xxxeee
xss@xss [09:47:09] : ~/Code
$ cat test.cpp
template <class T>
class TB{
public:
TB(T& that){
this.value = that.value;
}
friend void T::foo(void);
private:
int value;
};

我上面并没有生命一个 TA, 直接用 T 代替, 但是实际上也是可以编译通过的.
这样的话, 你至少不用考虑 TA 的问题, 因为 T 可以是任何东西.....
hackpro
2017-05-23 14:29:53 +08:00
@xss 感谢回复 不过大兄弟你这段代码没考虑 namespace 问题啊
另外代码编译没有问题 但是没有实质的调用 编译器并不会将这段代码实例化……
xss
2017-05-23 14:48:14 +08:00
@hackpro 我只是再跟你说解耦的问题.

namespace 也不影响应该,
TB<othernamespace::TA>(objTA)

这个完全是你在实例化这个模板类的时候需要考虑的问题.
你只需要对 class TB 有个合理的设计就行了.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/363012

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX